在圆内平均分布的点

要想在一个圆内随机取一个点不难,通常可以分成两个步聚:

  1. 随机选一个角度(0~360);
  2. 随机选一个小于半径的长度。

代码(processing):

float rad=random(TWO_PI);
float dist=random(1)*radius;
point(cos(rad)*dist, sin(rad)*dist);

这样可以确保点落在以原点为中心,半径为radius的圆内。

但是如果不断地重复这样取点,最终会发现在圆心的点更容易被取到,也就是说圆内的点被取到的概率不平均!最终会出现如图最左边这样的分布:

circle

而我们想要的效果是像图中间那个圆那样的分布。

后来在 Keith Peters 大师的 Foundation ActionScript 3 Animation Making Things Move! 一书中看到了这个非常漂亮的算法。来自他的朋友 Sean O’Shell:

float rad=random(TWO_PI);
float dist=sqrt(random(1))*radius;
point(cos(rad)*dist, sin(rad)*dist);

嘿,奇迹发生了。聪明的你或许已经发现了其中的奥秘。将 random(1) 开方后,原本靠近中心的点被扯开了,正好平均地分布在圆中。

至于数学证明,我还没有找到 :)

2013/03/06 UPDATED:在 Physically Based Rendering 一书中有对单位圆均匀采样的详细论述,可以参考一下 codeboycjy 的这篇日志《PBRT学习笔记:在单位圆内部均匀采样》http://blog.csdn.net/codeboycjy/article/details/6225886

Lua> io.write(“\27[2J”)

Programming in Lua 第六章 More About Function 开头有一个例子。它在终端屏幕上输出一个用*号组成的正弦曲线:

function eraseTerminal()
	io.write("\27[2J")
end
-- writes an `*' at column `x' , row `y'
function mark (x,y)
	io.write(string.format("\27[%d;%dH*", y, x))
end
-- Terminal size
TermSize = {w = 80, h = 24}

-- plot a function
-- (assume that domain and image are in the range [-1,1])
function plot (f)
	eraseTerminal()
	for i=1,TermSize.w do
		local x = (i/TermSize.w)*2 - 1
		local y = (f(x) + 1)/2 * TermSize.h
		mark(i, y)
	end
	io.read() -- wait before spoiling the screen
end

plot(function (x) return math.sin(x*2*math.pi) end)

这段看似没什么稀奇的 example code 里第二行的 “\27[2J” 和第七行的 “\27[%d;%dH” 吸引了我。

我在 Lua 解释器的交互模式下,动手试了一下 :

io.write("\27[2J")

屏幕被清空了,就好像在终端里执行了 clear 一样!而根据注释说明:

io.write(string.format("\27[%d;%dH*", y, x))

这段代码的用途就是在屏幕的第y行,第x列打印一个*号。

这个神奇的 \27 打头的字符串是什么东西呢?\27 在 ascii 码表示的是 <ESC> ,但这和终端又有什么关系?

经过一番搜索,在 google 的帮助下终于找到源头:Terminal codes – http://wiki.bash-hackers.org/scripting/terminalcodes

Terminal (control-)codes are needed to give specific commands to your terminal. This can be related to switching colors or positioning the cursor, simply everything that can’t be done by the application itself.

这是一种用来控制终端界面的指令,可以改变光标所在的位置和颜色——那些CLI程序无法完成的事情。

在另一份代码中,我找一了一个封装好的终端控制代码。更直观了说明了 Terminal codes 的作用:
https://bitbucket.org/lmb/diluculum/src/44c52aec561b/Lua/ANSITerminal.lua

列出 cocos2d-x Android 项目中的 cpp 文件

将 cocos2d-x 的项目移植到 android 平台时,需要用 build_native.sh 来编译 cpp 文件。而在此之前,还要将项目用到的所有 ../../Classes/*.cpp 增加到 proj.android/jni/Android.mk 文件的 LOCAL_SRC_FILES := hellocpp/main.cpp \ 这行下面。

通常一个大项目会有数十甚至数百个cpp文件,如果逐一手工添加的话,必定累死。基于 DRY原则(don’t repeat yourself),必须要有一个脚本来快速完成这件事。对于强大的 shell 只要这样一句就 ok 了。

find ../../Classes/. -name "*.cpp" | xargs

注意:以上命令需要在 Android.mk 所在的 proj.android/jni 目录下执行,这样才能得到正确的相对路径。这样可以得到如下内容:

MAC:jni mutoo$ find ../../Classes/. -name “*.cpp” | xargs
../../Classes/./AppDelegate.cpp ../../Classes/./Layer/GameLayerPlus.cpp ../../Classes/./Layer/MainLayer.cpp ../../Classes/./Layer/MenuLayer.cpp ../../Classes/./Layer/ModeLayer.cpp ../../Classes/./Layer/PauseLayer.cpp ../../Classes/./Layer/ResultLayer.cpp ../../Classes/./Layer/ScoreLayer.cpp ../../Classes/./Layer/SplashLayer.cpp ../../Classes/./Layer/TimerLayer.cpp ../../Classes/./Menu/ConfigMenu.cpp ../../Classes/./Menu/MainMenu.cpp ../../Classes/./Menu/ModeMenu.cpp ../../Classes/./Menu/PauseMenu.cpp ../../Classes/./Scene/GameScene.cpp ../../Classes/./Scene/MainMenuScene.cpp

其实在 proj.android/jni 的目录下已经有一个 shell 脚本可以完成这件事了,就是那个不起眼的 proj.android/jni/list.sh ,使用方法也很简单,指定一个参数作为要搜索的目录即可

./list.sh ../../Classes

但不幸的是,执行完了啥也没发生,还报错了:

MAC:jni mutoo$ ./list.sh ../../Classes
-bash: ./list.sh: /bin/bash^M: bad interpreter: No such file or directory

^M 是什么情况!?其实这是一个典型的编码错误,cocos2d-x-2.0~2.1都有这个问题。用 vim 神器打开 list.sh 查看其编码方式:

MAC:jni mutoo$ vi list.sh
:set ff?
fileformat=dos

这说明 list.sh 是一个 dos 编码的文件——不知是哪个大神动了这块码酪……不要紧,知错即改,拿来主义:

:set ff=unix
:set ff?
fileformat=unix

2013/02/19 Updated: 已经提交修改后的代码到 cocos2d-x@github

Good,现在历史错误被纠正了,保存重试之:

MAC:jni mutoo$ ./list.sh ../../Classes
../../Classes/AppDelegate.cpp \
../../Classes/Layer/GameLayerPlus.cpp \
../../Classes/Layer/MainLayer.cpp \
../../Classes/Layer/MenuLayer.cpp \
../../Classes/Layer/ModeLayer.cpp \
../../Classes/Layer/PauseLayer.cpp \
../../Classes/Layer/ResultLayer.cpp \
../../Classes/Layer/ScoreLayer.cpp \
../../Classes/Layer/SplashLayer.cpp \
../../Classes/Layer/TimerLayer.cpp \
../../Classes/Menu/ConfigMenu.cpp \
../../Classes/Menu/MainMenu.cpp \
../../Classes/Menu/ModeMenu.cpp \
../../Classes/Menu/PauseMenu.cpp \
../../Classes/Scene/GameScene.cpp \
../../Classes/Scene/MainMenuScene.cpp \

Well Done!但……这是最简单的方法吗?不,你还需要把这些内容复制到 Android.mk 里面,每次修改代码增加新类后,你得重复 list.sh 然后编辑 Android.mk 文件,最后再 build_native.sh ……

DRY!其实 Android.mk 这个 makefile 也是脚本……后面你懂的。

在 Chrome 中实现复制/粘贴的方法

在v2ex上看到有人讨论使用现代浏览器(如chrome/firefox)访问优酷,希望点击分享按钮复制视频地址时会弹出诸如这样的提示:

v.youku.com 上的网页提示:
您使用的浏览器不支持此复制功能,请使用Ctrl+C或鼠标右键。

想到在 Chrome 中使用 vimium 扩展时确实能很自如地复制链接,那么 vimium 是如何现实的呢。我翻了一下 vimium 由 CoffeeScript 编译后的 javascript 代码,其中有一个闭包专门完成复制与粘贴功能。代码如下:

// Generated by CoffeeScript 1.4.0
(function() {
  var Clipboard, root;

  Clipboard = {
    _createTextArea: function() {
      var textArea;
      textArea = document.createElement("textarea");
      textArea.style.position = "absolute";
      textArea.style.left = "-100%";
      return textArea;
    },
    copy: function(data) {
      var textArea;
      textArea = this._createTextArea();
      textArea.value = data;
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand("Copy");
      return document.body.removeChild(textArea);
    },
    paste: function() {
      var textArea, value;
      textArea = this._createTextArea();
      document.body.appendChild(textArea);
      textArea.focus();
      document.execCommand("Paste");
      value = textArea.value;
      document.body.removeChild(textArea);
      return value;
    }
  };

  root = typeof exports !== "undefined" && exports !== null ? exports : window;

  root.Clipboard = Clipboard;

}).call(this);

请注意 document.execCommand(“Copy”); 和 document.execCommand(“Paste”); 这两句。这个闭包通过 _createTextArea() 方法巧妙地构造一个在页面外的文本框(不可以是隐藏的,因为如果隐藏了就无法选择其中的文本了),然后将要复制的内容填到框中,并通过 select() 方法选择文本框中的内容。最后执行 document.execCommand(“Copy”); 将内容复制到剪贴板中并销毁文本框。这是一个很妙的方法,但我更关心的是这个函数能否在一般的页面中调用呢?
我把上面这段代码保存到 HTML 中,并在结尾调用以下代码进行测试:

window.Clipboard.copy("hello world");

程序全部执行了,但剪贴板中结果没有出现”hello world”。这表明 google chrome 没有把这个 API 开放给网页开发者。出于安全性考虑,只有在扩展程序中才可以使用,并且要在扩展的 manifest 中请求 “clipboardRead” and “clipboardWrite” 这两项权限。

想想这也挺合理的,谁也不想在浏览网页的时候,剪贴板就被植入广告了——我还真干用这种事——用的是flash,hah。于是有人利用 flash 的这个特性绕过了浏览器的限制,发布了 Zero Clipboard 这个项目用于实现跨浏览器访问剪贴版。项目地址:https://code.google.com/p/zeroclipboard/ 如果你真的有这样的需求,就考虑用它吧。当然,这是需要浏览器有 flash player 支持的。

鼠须管之五笔配置

实习生涯过去半个多月了,公司给配的iMac昨天到了。充裕的硬盘和内存,使用起来就是爽快,不用像折腾 Macbook AIR 那样小心翼翼。新机子到手后,当然有很多事要做。装上各种开发工具和常用软件,当然少不了输入法!

小时候接触电脑比较早,99年当时五笔输入法很火热,学电脑都会先学打五笔。当时的拼音没有像今天这么智能,超级难用。所以五笔在大陆地区中文输入法的地位还是挺高的。没学多久就能比较流利地打字了……后来,随着年龄的增长,我的拼音水平是越来越差,所以更加依赖五笔。

Windows 下五笔输入法特别多,王码五笔(86版),极品五笔,念青(繁体)五笔,QQ五笔,甚至现在很流行的五笔拼音混合输入法等等……加上网络词库等,更是越来越好用。后来转战 Linux 平台,试了一些输入法,如 iBus,fcitx 等等,都挺不错的,我比较偏好后者。

刚开始用 Mac 的时候,在输入法上有些水土不服,一方面是按键不太适应,另一方面是知道的软件不多。系统自带的五笔很不好用,不能联想选词,而且会把字根直接显示在屏幕上,特别恶心。试过了QQ五笔 for mac,打字的时候非常卡,词库太大了,华而不实,而且五笔拼音混合输入很不给力,没有 fcitx 来得方便。后来在网络上遇见了强大的鼠须管(Squirrel),使用后感觉真是太棒了,灵活的定制,小巧的词库,打字时非常流畅,五笔拼音混合输入也非常方便。

五笔有些特点:最多四码一字,很少选词。如果遇到选词,通常位置都很固定,不需要依赖词频变化位置,例如:去(fcuu)云(fcuu)支(fcuu),只要凭借少量记忆就能摸准位置。不像拼音这样的,会依个人使用习惯变化,也不太需要网络支持。所以词库越小越好。偶尔记不清字长什么样的,再用拼音打就成了。这也是近年来五拼法很流行的原因。

鼠须管

鼠须管来自 rimeime(中州韵输入法引擎 | Rime Input Method Engine)
项目地址:https://code.google.com/p/rimeime/

鼠须管是中州韵输入法引擎在Mac版本下的别称。下载安装后在“系统偏好设置>语言与文本>输入源”中启用即可。如果你想使用拼音输入法,那么安装完即可直接使用,但我的目标是五笔,所以需要进一步定制。

配置文件

鼠须管的配置文件都在 mac 系统的 “/Users/<your_name>/Library/Rime” 目录下,通常在用户目录下是不显示 Library(资源库)文件夹的,所以可以在 finder 中按下”Shift+Command+G”,前往”~/Library/Rime”。

在这个目录中有很多以 .yaml 为扩展名的文件。这些是鼠须管的配置文件。可以直接用你喜欢的文本编辑器查看。

根据维基百科的介绍,YAML 格式是一种可读性高,用来表达资料序列的编程语言。它最大的特点就是“在缩排中空白字符的数目并不是非常重要,只要相同阶层的元素左侧对齐就可以了。”这意味着你用两个空格或四个空格作为缩进(indent)都是可以的。

鼠须管提供了一个很方便用户自定配置的方法,只要创建一个文件名(.yaml之前)与要定制的文件相同,扩展名为.custom.yaml 的文件即可。例如要定制 default.yaml 只需要增加一个 default.custom.yaml 文件即可。而文件首行以 patch: 开头,之后的所有配置项缩进一个层级。

定制五笔输入法

patch:
  schema_list:
    - schema: wubi_pinyin

将以上代码保存为 default.custom.yaml 然后选用鼠须管输入法,并在输入菜单中使用“重新部署”,这时输入法就变成了五笔拼音输入法。如果只想使用五笔,可以将 wubi_pinyin 替换成 wubi86 。

外观定制

同样的,我们还可以灵活定制输入法的外观:

patch:
  style:
    horizontal: true
    font_point: 16

将以上代码保存为 squirrel.custom.yaml 即可,记得“重新部署”输入法。更多相关的配置项可以参考对应文件,或者官方的《定制指南》

USB网卡 for Macbook Air

用了 Air 有那么一段时间了,有爱也有恨,不过还是爱更多一点,hah。Air 的轻薄注定它容不下一个小小的 RJ42 以太网接口(可见它有多薄!),所以在一到晚上就断电断网的校园环境,很有必要配备一个 USB 网卡。

至今我买了两块 USB 网卡,前一块不知道怎么地就坏了。还好这东西不贵,十几二十块就能淘到。但是选购的时候要注意一些事项:

网卡芯片

市面上的 USB 网卡其芯片有很多版本,常见的有 AX88772A/9600/9700 等。

AX88772A 芯片比较通用,大多数系统不需要安装驱动程序即可即插即用,Windows 可通过网络自动获取驱动,Air 插上就直接识别了。缺点是发热量挺大的,我用的第一块USB网卡就是这个芯片,估计是用对等网线在PC和Air间直接传大数据后烧坏了(长时间维持在10M/s)。

9600/9700 芯片需要手动安装驱动后才可以使用。驱动程序随盘附赠,也可直接在网络上下载。Air 装完驱动后还需要重新启动电脑才可以识别到网卡。9700 芯片可以自动切换10Mbps/100Mbps速率,发热量明显比 AX88772A 要小多了。

Vimium 中文版 – 像黑客一样使用浏览器

很久以前申请了 Chrome 开发者,一直也没做些什么扩展。最近给同学介绍扩展的时候推荐了 Vimium ——这是一个我非常喜欢的工具,可以让我以 Vim Editor 的方式来浏览网页。特别是看漫画的时候,我可以手不离键地操作甚至换页(双击“]”键)。

但是很多网友抱怨它的英文键盘说明看不懂,所以我决定借助开源的力量将它做一次简单的汉化,于是就有了:

Vimium 中文版

Vimium 是一个 Google Chrome 浏览器扩展程序。受到伟大的 Vim 编辑器的启示,它向浏览器提供了一系列用于快速浏览网页的快捷键。

本项目是基于 philc/vimium 的汉化版本.

项目地址:
https://github.com/mutoo/vimium

Chrome 扩展地址:
https://chrome.google.com/webstore/detail/vimium-中文版/bedaaeieijphebekbfnkpllociojglip?hl=zh-CN

给页面链接添加平滑滚动效果

做完厦图答题神器,发现即使是这样一个简单的小页面,也可以添加上很赏心悦目的效果。正好我想要给页面的链接 (local-links) 加上平滑滚动效果,搜索了一下发现 jQuery 的插件正好提供了这样的功能——$.scrollTo();

$.scrollTo(); 是一个能平滑滚动到页面上特定位置或元素的 jQuery 插件,还提供了丰富的动画效果。

插件介绍:  http://flesler.blogspot.com/2007/10/jqueryscrollto.html
官方演示: http://demos.flesler.com/jquery/scrollTo/

原来的页面链接,如 <a href=”#local-link“>GO-TO-LOCAL-LINK</a> 会让页面直接定位到 <div id=”local-link“> 所在的位置。这种跳转是生硬的,而想要实现平滑的滚动到目标元素,就要用到 $.scrollTo(); 了:

$.scrollTo("#local-link", 500); // 将页面平滑滚动到 id="local-link" 的元素所在位置, 时间:500毫秒

为了响应所有的页面链接,可以使用 jQuery 选择器,找到所有带有当前页面链接的 <a href=”#xxx“> 标签,并将页面平滑滚动到指定位置:

$('a[href^=#]').click(function(e) {
	$.scrollTo($(this).attr('href'), 500);
	return e.preventDefault();
}); 

实际上 $.scrollTo(); 的作者还发布了另一个叫 $.localScroll(); 的插件,除了完成上述功能外还做了额外的优化。只需要一句话即可:

$.localScroll();

插件介绍: http://flesler.blogspot.com/2007/10/jquerylocalscroll-10.html
官方演示: http://demos.flesler.com/jquery/localScroll/

$.localScroll(); 默认的动画时间是 1e3 也就是 1000ms = 1s 。如果需要自定义的话,只需要传入一个包含 during 属性的对象即可:

$.localScroll({during: 500}); // 平滑滚动,时间:500毫秒

现在厦图答题神器的页面上已经有平滑滚动的效果了,成果展示 http://xujc.sinaapp.com/library/

图书馆入馆考试自动答题(2012)

今年课业很闲,在新生群里认识了很多学弟学妹,其中不乏对技术很有兴趣的同学。于是打算找几个志同道合的一起做些小项目。

正好他们军训过后要参加图书馆入馆培训,培训之后需要参加一个在线测试,分数高于80分的才可以从图书馆借阅书籍。于是我把去年写的代码翻了出来,重新运行了一下,发现很多题目已经过期了,正确率已经不足40%。这是一个不错的信号——就拿这个小项目动手吧。

这次的目标是制作一个可以自动完成入馆考试的脚本,并提供一个网页供他人使用。

技术分析

图书馆通识测验地址 – http://210.34.218.48/exam/ (公网访问出奇的慢)

这是一个基于 asp.net 的在线测试系统,题目类型有:单选题、多选题以及判断题。最坑爹的地方在于——完全是用 .net 那套 updatePanel (Ajax) 来响应操作。每次点击一个选项,都要 ajax 通讯一次,把整个题目信息更新一遍。对于公网用户,平均响应速度几乎超过1s~幸好我是忠实的教育网用户。

对付网页版的在线测试,直接用 greasemonkey 脚本最方便了(但只支持firefox和chrome)。考虑到跨浏览器支持,还是决定采用比较小众的 js 注入法——通过浏览器书签(或地址栏)将外部脚本注入到当前页面。其余的所有操作就由 js 控制页面元素来完成。

iframe 的妙用

还有一个问题就是在线测试的不同题型分布在不同页面。当完成一种题型后切换到另一个页面,之前注入的 js 脚本就没了,需要重新注入一次。这大大加重了用户的操作负担,而且在使用教程上也不容易解释。后来想到一个取巧的方法,就是将被注入的页面自嵌到 iframe 里,通过控制 iframe 到实现自动页面切换:

/* 把网页放到浮动框架中 */
document.write('<iframe id="iframe" name="content" src="'+location.href+'" style="width:100%;"></iframe>');
/* 响应页面载入事件 */
frame.onload = function(){ /* do_something(); */ }
/* 跳转页面 */
function redirect(url){ frame.src = url; }
/* 得到页面信息 */
content.location.href;

注意到这里使用了 id=”frame” 和 name=”content” 。经过测试发现,通过 id 获取到的是 iframe 元素本身,可以响应各种事件,如 onload ;而通过 name 获取到的是 iframe 的内容——一个 window 对象,包含了被嵌入网页的所有信息。这样一来,就可以通过 iframe 做任何事情了。不过由于安全沙箱的限制,通常只允许对相同域名下的网页进行操作。但本例是通过 js 注入,所以安全沙箱也无法阻档,hah。

其实只要两行代码,就可以防止网页被嵌到框架里:可以参考阮一峰老师的这篇博客《防止网页被嵌入框架的代码》,如果管理员加了这个脚本的话,我就只能老老实实地分次 js 注入了。

updated 2012-09-26:经过测试确认 IE系列的浏览器不能响应通过这种形式创建的iframe的各种事件。

可行性分析得到的结果令我满意,接下来的工作就是收集题库了。由于这个测试系统允许无限次答题,并且每次答题结束后都会公布答案信息(其实只要直接访问测试结果的页面就行了)。所以只要多试几次,就能拼凑出大部分题目了。在这里感谢12级物联网专业的林智同学帮我整理了题库。

晚上花了两个多小时和林同学结对编程,终于把基本的功能实现了,录了一段视频让大家偿偿鲜,接下来将近一步完善并修复一些 bug,最后制作并发布一个公测页面。敬请期待 :)

[vsw id=”http://player.youku.com/player.php/sid/XNDU0MzI3MDI0/v.swf” source=”youku” width=”480″ height=”400″ autoplay=”no”]

updated 2012-09-26:

以上是使用定时器控制的答题情况。在实际使用中会出现很多问题,尤其是在宽带访问出现 ajax 更新延时,正确率严重下滑!于是我考虑能否通过响应 ajax 回调事件来进行答题控制。

updatePanel 之迷

由于对 Asp.Net 比较不熟悉,于是直接在 chrome 开发人员工具下跟踪调试了一个下午才找到用于响应事件的代码——Sys.WebForms.PageRequestManager 类,其中有两个方法 add_endRequest() 和 remove_endRequest() 可以自定义ajax请求结束时的回调函数。

Sys.WebForms.PageRequestManager.getInstance()
.add_endRequest(callback);]

但是通过 iframe 操作 add_endRequest() 时不知何时种原因 chrome 出现了异常:

iframe.Sys.WebForms.PageRequestManager.getInstance()
.add_endRequest(callback);

RangeError: Maximum call stack size exceeded

为了解决这个问题,我改用直接操作事件列表的方式来处理这个方法:

iframe.Sys.WebForms.PageRequestManager.getInstance()
._get_eventHandlerList()
._getEvent("endRequest", true)
.push(handler);

这样一来就可以知道答题操作后结果返回的确切时间了,在回调函数里决定接下来做什么就可以了。以下是效果预览:

[vsw id=”http://player.youku.com/player.php/sid/XNDU0Njc3NTY0/v.swf” source=”youku” width=”480″ height=”400″ autoplay=”no”]

跨浏览器支持

在 chrome 中,直接使用对象的 name 或者 id 即可以获取到对象;而在 firefox 中则建议使用 w3c 标准的 document.getElementById() 来获取对象,甚至没有提供使用 name 来获取对象的api,只有 document.getElementsByName() 获得对象数组。

为了快速移植脚本使其适应其它浏览器,我写了一个简单的 function 来获取对象。需要引用对象的话,将 iframe[“name_or_id_for_element”] 统一改成 getFrameElement(iframe, “name_or_id_for_element”); 即可:

function getFrameElement(frame, name_or_id){
 var element = frame.document.getElementById(name_or_id);
 if(!element)
  element = frame.document.getElementsByName(name_or_id)[0];
 return element;
}

现在脚本已经能很顺利地在 chrome/firefox/opera/safari 执行了。而 IE 则不能很好地处理 iframe 对象,所以暂时不考虑 IE 的自动答题脚本。这里提供了一个半自动版的演示,需要多次 js 注入:

[vsw id=”http://player.youku.com/player.php/sid/XNDU1MDA1ODcy/v.swf” source=”youku” width=”480″ height=”400″ autoplay=”no”]

另外,IE6 甚至没有提供 Array.indexOf() 方法,需要自己实现:

if(!Array.prototype.indexOf){
 Array.prototype.indexOf = function(val){
  var value = this;
  for(var i =0; i < value.length; i++){
   if(value[i] == val) return i;
  }
  return -1;
 };
}

接下来将着手开始制作公测页面,我考虑在网页上加入 kill ie6 代码:

Let’s Kill IE6 – https://code.google.com/p/letskillie6/

敬请期待~

updated 2012-09-27:

厦图答题神器公测地址已发布:http://xujc.sinaapp.com/library/ 欢迎同学进行测试 :)

[vsw id=”http://player.youku.com/player.php/sid/XNDU1MjEyMzQw/v.swf” source=”youku” width=”480″ height=”400″ autoplay=”no”]

SAE 中级开发者证书

九月初SAE更变收费制度,对未通过开发者认证的免费用户实施按月收费,很大程度上影响了一些开发者的积极性。

正好暑假完成了天猫来找茬应用的开发,且在公测时已有近万人参与游戏。随后我参看了SAE开发者认证的申请条件,其中中级开发者:

  1. 至少有1个应用是原创应用
  2. 原创应用功能基本完整
  3. 应用须超过1000人次使用

一看已经符合申请资格了,果断上交了申请表。如果通过的话,可以享有优厚的福利:

  1. 每月免费获得1万云豆
  2. 一次原创应用推广机会
  3. 获得SAE授权荣誉证书

价值: 1200元/年

今天收到EMS寄来的快件,里面是《新浪云计算开发者荣誉证书》。嘿嘿,这下可以放心使用SAE了。有空做些好玩的东西,下次争取有机会申请个高级开发者。

图为 Weibo 分享时自动生成的图片,并非证书扫描件