原先的验证码是几个较难识别的字母,这对视力不佳的人是一种赤裸裸的歧视。考虑到这种情况,我将验证码改成了一道题,只要从四个词语中找出与众不同的一个词并填到后面的文本框里即可。
分类: 个人设计
基于xapian的相关度搜索项目初步完成
最近两个月研究了相关度搜索引擎的一些知识,对Xapian和Omega(一个基于Xapian的应用)的代码进行了一定量的修改,开发出了一款轻量级的基于中文字典词库的相关度搜索引擎。
这个搜索引擎的功能是:从数据库的一个表中取出内容字段的数据,利用基于中文字典词库的分词算法,建立这些数据的索引。根据索引,我们可以检索到与某条记录相关的其它记录,以及扩展分词列表。
扩展分词列表的概念是负责eYou邮件网关算法的同事介绍的,她认为仅凭一个分词找到相关记录的算法过于刻板,应该是先找到与这个分词语义最相关的一组分词,然后针对这组分词进行更精确的搜索。
上图是我将占座网随笔数据导入后的查询结果,这是一个demo页面的截图,第一篇ID为105121的文章的相关文章从第二行开始列出,看起来效果还算可以。
建议对银行系统排号服务作如下改动
每次到王府井的中国银行营业厅时,前面总有三五十人在排队。为了避免耽误工作,往往是吃饭前去领个号,吃完饭再去办理业务。一方面是很多人在无聊的等待,另一方面是很多人无法忍受过长的等候而离开,从而导致大量废号的产生。
我建议操作流程改为这样:
- 按下触摸屏上的“对公业务”、“个人储蓄”等功能。
- 屏幕出现提示信息:“您前面还有××位客户正在排队,预计您还需等待××分钟。我们为您提供了手机提醒服务,请选择:”
需要客户设置的信息如下:- 当您前面排队的客户数少于 [ 5 ] 位时,向您发出提醒。
- 请输入您的手机号码: [ 13xxxxxxxxx ] 。
- 请输入提醒方式:[ ] IVR语音通知(每条收费1元);[ ] 短信消息通知。
- 在用户设置完成后,打出排号单。
如何测出头的体积?
被经常性骂作猪头的同志们注意了,其实头的体积是可以被较为精确的量度的,了解自己是为了更好的打击敌人。
准备工作:找一个比头稍大的有刻度的容器,并将其灌满水(如果水不纯,请事先测出密度d);一个体重秤。
首先把头洗净,尽量去除可溶水的物质,站到秤上记录下示数G0,然后把头放到容器中,稍后取出,立即站到秤上记录下示数G1。这时去读容器中被头排出的水的体积V’。
得到上述三个读数后,你的头的体积
V=V’ – (G1-G0)/d 。
一个迟到罚款数额的计算公式
上班迟到要扣钱,一个简单的分段函数是无法达到很强的约束力的。于是我设计了一个略微复杂的函数,供地球上的HR参考。
S = S0 + dTA1+ρn/N
各参数代表的意义如下:
S0:金额基数,即最低罚款额。
d:比例系数。
n:在该人到达公司前,当天公司已经迟到的总人数(人)。
N:当天公司共需签到的总人数(人)。
A:金额基数(元),可以为一个与T相关的函数。
T:该人当天迟到的时间(分钟)。
ρ:比例系数,用于调整N对S的影响。
简述:某个人迟到需缴纳的罚款,跟当天迟到的分钟数线性相关。随着迟到人数占公司总人数的比例不断增加,罚款数额也会增加。
这个函数将会起到如下作用:T对S的约束会促使员工无论迟到了多久,都要尽快到达公司,否则罚款是随时间不断上涨的。n对S的约束会促使员工尽量早到公司,否则总会比前一位同事多交罚款,并且客观上会降低迟到员工的总数。
给本站加上了字数统计功能
我在每篇blog的尾部,加上了对该篇文章的字数统计功能,其中包括总的汉字字数,以及出现的不同的汉字的个数,对外揭示了对汉字量以及字频的统计信息,这个功能的实现非常简单,就是一段javascript代码,如何使用,就看大家的才艺了:
function CountChineseCharacters(Words) {
var W = new Object();
var Result = new Array();
var iNumwords = 0;
var iTotal = 0;for (i=0; i<Words.length; i++) {
var c = Words.charAt(i);
if (c.match(/[u4e00-u9fa5]/)) {
if (isNaN(W[c])) {
iNumwords++;
W[c] = 1;
}
iTotal++;
}
}
Result[“numwords”] = iNumwords;
Result[“total”] = iTotal;
Result[“avg”] = parseInt(iTotal/iNumwords*1000)/1000;
return Result;
}
var res = CountChineseCharacters(document.getElementById(“id_entrytext”).innerHTML);
document.getElementById(“numwords”).innerHTML=res[“numwords”];
document.getElementById(“avg”).innerHTML=res[“avg”];
例如,可以这样用:
var res = CountChineseCharacters(document.getElementById(“id_entrytext”).innerHTML);
document.getElementById(“numwords”).innerHTML=res[“numwords”];
document.getElementById(“avg”).innerHTML=res[“avg”];
link2rss 0.1版代码下载
link2rss的功能是将一篇网页中的链接转换为rss文件,用户使用客户端订阅这个rss文件,就可以获取这篇网页链接内容的更新,对于新闻资讯类网站尤为适用。
最近几天钻研了perl,写了一个简陋的程序完成了这个功能。
这是一个perl程序,点击这里下载。使用方法:
perl link2rss.pl <url> > <filename>
url: 一个网页,以http://开头,此外网页中至少还要有一个斜杠,如http://news.sina.com.cn应写为http://news.sina.com.cn/ 。
filename: 要导出的目标xml文件,如果需要使用客户端订阅,那么这个文件需要放在http服务的目录下。
一个典型的例子:perl link2rss.pl http://news.sina.com.cn/ > /usr/local/apache/htdocs/news.sina.xml
这个程序需要LWP::Simple和HTML::Parser支持,请下载并安装相关的模块。
不管考试成绩是多少分,link2rss就算是毕业了,希望这个程序可以减轻朋友们在访问门户网站时寻找链接的痛苦。如果你有一台托管服务器,可以把这个程序放在服务器上定时运行,如果没有,也可以放在本地执行。本站也会稍后提供这样的服务,提供若干条xml供大家订阅。
playlist的随机播放算法
-
一些约定
一个playlist是指一个播放序列,其中的每个条目称为一个entry。每个条目对应一个计数器属性,称为counter,counter是实现这个算法的关键。
-
playlist初始化
将一些entry序列导入playlist,每个entry对应的counter置为0。
-
播放一个entry
- 开始播放/播放一条新的entry时:如果是新的entry,则新entry对应的counter加1;如果仅仅是repeat同一首歌,则counter不变。
- 播放中切换时:
- 取出当前playlist中各个entry中最小的counter值,记为counter_min;
- 取出所有counter值等于counter_min的entry,随机播放其中一条。
-
添加一条entry到playlist
- 取出当前playlist中各个entry中最小的counter值,记为counter_min;
- 这条entry追加到playlist末尾;置这条entry的counter为counter_min。
-
删除一条entry
略。
对小规模团队的开发流程设计
最近公司在进行一系列新模块的开发,在痛苦开发的过程中,大家不时在一起进行总结等思维体操活动。上周六中午加班,几位同事一起聊了聊最近协同开发的感受,我从中受益匪浅。
首先提到过于民主化的开发模式导致了交流成本的增加,这些成本分散了研发人员真正用于开发的精力,显得很不划算,但是针对这个现象,一直没有可行的解决办法。其次是一些具体的合作开发模式导致无法控制整体进度。我们按照自己的思路,针对目前的实际情况,勾勒了一个理想化的开发流程。
点击左上角图片可以看到这个流程图,以下是对各个字母所代表的连线的注解:
A、项目经理与公司决策层的沟通,以确定这个需求有没有足够的人手和可行性去实现,以及与现有产品的依存关系。
B、公司决策层与市场/策划部门的交流,这个过程将进行的相当充分,并且是反复、长期的,它致力于从用户的角度对需求进行细化和分解。
C、市场部门需要针对细节问题与项目经理交流,以确定这个需求有没有可行性去实现。
D,E,J、这是整个产品的架构设计过程,分为UI架构设计和程序架构设计两部分。首先架构师需要与项目经理达成思想上的一致,随后进行设计。这个设计必须是便于分工、维护和扩展的,而且要能够承受一定强度的原型开发压力。UI架构师将根据界面逻辑对产品实施分割,对每个界面上需要放置的内容了如指掌。程序架构师在与全体开发人员民主讨论后,制定出自底至顶的程序层次(例如class、library等等),并划分出功能模块(例如首页、内容列表、后台管理、帮助系统等等)。UI架构师与程序架构师之间需要就功能划分、文件命名规则等等达成一致意见,并不断在开发中完善思路。
F、美工使用photoshop等工具设计界面,并完成图片切割工作。
G、网页设计师负责书写静态模板。如果人手缺乏,这个位置可从程序开发人员中抽调。
K、美工与网页设计师之间需要进行一些协调。一些美工的设计思维并不能完美的体现在网页上,因此需要不断的磨合与修正,达到双方都满意的结果。但相对来说,美工完成的作品并不需要做太多的改动,因此这里采用单向箭头标示。
H、对底层逻辑(如类、方法、库的设计),以及相关文档的整理。如有精力可以进行小规模的测试,确保日后的开发工作顺利进行。
I、当底层接口以及相关文档完成后,模块化的拼接将变的比较轻松,这个流程将完成基本模块到外部功能的构建工作。
L、这是程序开发人员需要付出最多交流成本的地方。很多的底层模块在拼接过程中需要进行变动,例如增减参数,修改类、属性、方法的名称,将类、属性、方法移动位置等等。同时,外部的实现需要随着底层模块的更改、优化进行相应的调整。
M、产品成型后,将交付测试部门进行测试。测试部门返回一个报告,发送给项目经理和程序开发人员。在小规模的开发团队里,项目经理可以充当质量保证的角色,前提是他对项目的开发过程有一定程度的了解,否则,应当指派一名专门的质量保证人员来处理bug列表。
N、测试部门返回的报告本来是可以发给所有程序开发人员的,但不幸的是,测试人员只跟界面打交道,他们只注重结果,而不注重实现原理。因此bug列表一般需要交给负责界面逻辑的开发人员进行整理,然后分发给各个成员加以更正。在小规模的开发团队里,界面逻辑和底层逻辑可能是由相同的一批人来实现的,那么他们需要一个Bugzilla来协同处理这些bug。我们也建议测试人员使用同一套Bugzilla系统提交bug报告。
最后总结几点:一、详细分工的目的是为了降低交流成本。二、实际情况会使得开发工作复杂化,所以流程模型要能适应原型开发工作。三、文档和标准化的规范是极其重要的,它可以使开发过程工厂化,提高代码质量和可维护性。
一个网站相关服务模块的结构模型
我的梦想就是成为一名优秀的架构设计师,让所有物质流和意识流都能够按照我的图纸以最大效率运动着。今天讨论一个很浅的模型,这个模型是受了近期工作的一些启发,以及与同事的交流得到的,我给他起了一个伟大的名字--“B-S三层结构中服务器端物质流的运动模型”,供博士论文引用方便。
点击左上角的图片可以看到描述这个模型的简略的流程图。假设Service I – III是某服务商提供的三个服务,他们在数据库服务器(或集群)上各自拥有一个数据库,即Database I – III,每个Database只有跟其号码对应的Service才能直接访问,如果另外两个Service也想访问,则需要通过每个Service提供的内部API间接收发数据,传输方式可为SOAP或xmlrpc等等。每个API会针对不同的服务设定相应访问权限。
考虑到某些Service对数据库的读写频率有不同的要求,我们可以为不同的操作指派不同的Database Server。例如某Web论坛,它的读写频率比为10:1,那么我们可以使用Master和Slave服务器,Master以某个周期或实时向Slave同步数据,写操作被指派给Master,读操作被指派给1到n台Slave,当网友对论坛数据的实时性不敏感时,这种方式最能提升效率。
考虑到与第三方展开的合作,我们还可以为每个Service开发对外API接口。对外和对内的API接口会根据权限设置和合作方要求而有所不同,所以不能完全使用一套接口。另外,提供与第三方合作的前提是保证我们自己的服务依旧稳定,因此要对第三方的请求与响应放入队列。我能够设想到的队列是这样的:一、拥有请求和响应两种队列;二、假设本方服务允许第三方操作的并发线程数为N,那么请求和响应队列数量可为N的任何约数;三、允许某些第三方用户使用带外通道,带外通道中的数据会非常少,那么它们会以很高的优先级得到处理,即使其它通道排满了请求,也不影响带外通道的响应效率,可为特殊用户提供VIP服务,并理所应当的收取高额费用。