CallMeLater, Send sms message when you don’t want to answer the call.

CallMeLater is an open source Android application of mine. Say you’re driving, your phone rings, it allows you to easily send an pre-set SMS Text message to the caller and hang up the phone automatically.
Please visit https://github.com/myfamousgarden for all my open source projects.

发表评论

MongoDB issue : overflow of inc

在mongodb 1.0.6下测试, MongoDB 中update 操作会有一个整数溢出的问题。 代码如下:
$ gem list mongo

*** LOCAL GEMS ***

mongo (1.0.6, 0.18.3)
mongo_ext (0.18.3)
mongo_mapper (0.7.0)

>> require ‘rubygems’
=> false
>> require ‘mongo’
=> true
>> include Mongo
=> Object
>>
?> db = Connection.new(“127.0.0.1”, 27017).db(“mongo-test”)
=> #<Mongo::DB:0x1015adaf0 @name=”mongo-test”, @pk_factory=nil, @strict=nil, @connection=#<Mongo::Connection:0x1015afeb8 @size=1, @checked_out=[], @connection_mutex=#, @nodes_tried=[[“127.0.0.1”, 27017]], @logger=nil, @id_lock=#, @sockets=[], @nodes=[[“127.0.0.1″, 27017]], @timeout=5.0, @slave_ok=nil, @port=27017, @queue=#, @auths=[], @options={}, @host=”127.0.0.1”, @safe_mutexes={#=>#}>>
>>
?> coll = db.collection(“overflow”)
>> coll.drop
=> true
>> coll.update( { :text => “orange”}, { ‘$inc’ => { :number => 1312830289} }, :upsert => true )
=> nil
>> coll.find({}).next_document
=> {“_id”=>BSON::ObjectID(‘4c5a6e470159c60e4dd7337f’), “number”=>1312830289, “text”=>”orange”}
>> coll.update( { :text => “orange”}, { ‘$inc’ => { :number => 9999089876} }, :upsert => true )
=> nil
>> coll.find({}).next_document
=> {“_id”=>BSON::ObjectID(‘4c5a6e470159c60e4dd7337f’), “number”=>-1572981723, “text”=>”orange”}

但是如果把 整型 换成 浮点型 则不会有这个问题 :  coll.update( { :text => “orange”}, { ‘$inc’ => { :number => 1312830289.0 } }, :upsert => true )

发表评论

Buzz, turn your sms into image

Buzz http://github.com/myfamousgarden/Buzz is another open source Android application of mine. With this small application, you can select several templates(10 templates for now) and turn your sms into image.

I posted it into hiapk.com(the biggest android forum in china), I’m so glad that there are still some people like it…. http://bit.ly/dzlX0C http://bit.ly/czrlSF

发表评论

My first android open source project on github

I have created several android apps(free or pro) in the Android Market, the total downloads of these apps are more than 200,000, but they are not open source projects.  NextBigDay http://github.com/myfamousgarden/NextBigDay is my first android open source project on github, it’s a good start, I will push more personal projects on github in the future, and I have some very funny ideas about sms on the android, but I’ve been a bit of busy and lazzzzy these days…..\

NextBigDay is an Android clone of the web site:http://recursion.org/fun-birthday. I finished it in the first day when I went back to beijing to look for a new job…You can input a date in the app, and to find out when it will next be on Friday or Saturday. It’s a small project, it only have not more than 100 lines of java code, it’s very helpful to those people who want to learn to build the app on Android. I will not to commit it to Android Market, because it has some small bugs and I’m not so willing to fix it ….

发表评论

招聘是一个问题

最近两周我都在做招聘相关的工作, 因为从 chinahr 拿到的简历太多, 我每天都要打好几个电话进行电话面试来进行初步的筛选。 流程是首先是电话面试,如果通过就会安排应聘者到公司进行面谈,主要就是问一些技术问题或者做两个题目,目的是考察应聘者的实际编程能力和解决问题的能力, 最后把情况汇报给老板, 由他作决定. 很可惜, 在最近两周的电话面试和公司面试加起来不低于20个的情况下, 仅仅有一个面试者得到了我们的认可.

对于最近的面试情况, 总结起来我有几点认识。 第一点就是从 chinahr 过来的简历真不怎么样. 我们主要是招聘高级的工程师, 但是 chinahr 给过来的简历大部分都是应届生或者是工作不超过3年的初级工程师, 而且简历质量也不行. 另外如果求职者在找工作前能够好好的总结一下工作经验, 把简历稍微丰富一下, 那么对找工作的帮助会很大.

另外一点就是现在的学校教育不注重基础教育, 很多学生往往基础不牢固就急忙的学习 java/C#/Php, 就像跳到一个黄金铸造的大坑, 却不知道这个坑是怎么造出来的. 另外, 我在电话面试的时候不问相关的算法的问题, 就算是在公司面试的时候的问题也仅仅是稍微接触到一些算法而已. 并不是说非得会算法才能成为好的工程师, 要成为好的工程师不需要很精通算法, 要成为 super 工程师才需要精通算法. 在公司的这个阶段, 如果能招到super hacker当然美妙, 但能招到扎实肯干的人也是很不错的.

在电话面试里面, 我固定问的问题一般有三个 :

1. Java 里面的 ArrayList 和 LinkedList 的区别
2. Java 里面的 Hashtable 和 Hashmap 的区别
3. 数据结构中的 stack 和 queue 的区别

如果应聘者能够不加迟疑的答出这三个问题的答案, 那我就会接着问一些稍微深入的问题, 主要是网络和多线程方面的问题。但是很可惜,很多应聘者连这三个问题都不能很好的回答。

最后一点就是具有交叉编程能力的人太少。现在手头上的简历大部分是Java EE web 相关的, 并不是说这些应聘者不够好, 而是说应聘者的能力范围很有局限性,大部分人只关注与Java EE 方面,而忽略了Java SE 方面的实践。如果应聘者能够同时精通两种或者两种以上的语言或者平台或者技术,比如java/C++/Python/Ruby/Php/Amazon/GA/Rails/Django…..,那绝对是很大的加分项。因为随着系统的日益复杂,我们必然会引入不同语言开发的框架或者技术来解决面临的问题,因此也要求我们工程师熟练掌握不同的技能。

Comments (2)

monodb geospatial index

mongodb 1.3.3+ 以后提供了一个新的特性,增加了地理信息索引功能(Geospatial Index),利用 GI 可以可以很方便的实现原来要用一堆复杂sql语句实现的查找功能。

比如说我们有一个Store模型, 里面有一个 name 和 代表地理位置的 loc 数组,那我们可以这样定义 Store :

class Store
include MongoMapper::Document

key :name, String
key :loc, Array

end

插入几条测试数据来进行测试,注意loc 必须都是Number, 不能是 String 类型,否则加上 Store.ensure_index([[‘loc’, Mongo::GEO2D]]) 就会出现错误。

>> Store.all

=> #<Store loc: [37.2222, -122.8999], name: “test”, _id:ObjectID(‘4bc17e6b610422039f000001’)>, #<Store loc: [40.72426,-73.997779], name: “near”, _id: ObjectID(‘4bc17ecd610422039f000002’)>,#<Store loc: [40.72426, -73.997779], name: “near”, _id:ObjectID(‘4bc17f0d610422039f000003’)>, #<Store loc: [40.72426,-73.9978], name: “haha”, _id: ObjectID(‘4bc184b5421aa9039f000004’)>]

创建索引

>> Store.ensure_index([[‘loc’, Mongo::GEO2D]])

=> “loc_2d”

定义查找

>> center = [40.72426, -73.997779]

=> [40.72426, -73.997779]

>> radius = 2

=> 2

>> sushi = {“loc” => {“$within” => {“$center” => [center, radius]}}}

=> {“loc”=>{“$within”=>{“$center”=>[[40.72426, -73.997779], 2]}}}
>> Store.all(sushi)

=> [#<Store loc: [40.72426, -73.997779], name: “near”, _id:ObjectID(‘4bc17ecd610422039f000002’)>, #<Store loc: [40.72426,-73.997779], name: “near”, _id: ObjectID(‘4bc17f0d610422039f000003’)>,#<Store loc: [40.72426, -73.9978], name: “haha”, _id:ObjectID(‘4bc184b5421aa9039f000004’)>]

结合全文检索

>> sushi.merge!(“name” => “haha”)

=> {“loc”=>{“$within”=>{“$center”=>[[40.72426, -73.99777], 2]}}, “name”=>”haha”}

>> Store.all(sushi)

=> [#<Store loc: [40.72426, -73.9978], name: “haha”, _id:ObjectID(‘4bc184b5421aa9039f000004’)>]
还可以进行正则表达式匹配

>> sushi.merge!(“name” => /^n/)

=> {“loc”=>{“$within”=>{“$center”=>[[40.72426, -73.99777], 2]}}, “name”=>/^n/}

>> Store.all(sushi)

=> [#<Store loc: [40.72426, -73.997779], name: “near”, _id:ObjectID(‘4bc17ecd610422039f000002’)>, #<Store loc: [40.72426,-73.997779], name: “near”, _id: ObjectID(‘4bc17f0d610422039f000003’)>]
cool!

发表评论

EC2 笔记

最近两个多月来一直在折腾AWS EC2,感觉需要做一些笔记了

  1. aws api tools 的安装和设置要正确,这个是首要的事情。
  2. firefox elesticfox 这个extension 很方便。也需要设置key-pair
  3. 在instance上要打开端口不仅仅要在 instance 的 firewall 上打开, 还需要通过 aws api tools 的 ec2-authorize 命令来打开端口
  4. 及时把 instance shapshot备份到 aws ebs。 最好能够设定一个日常备份的脚本。 把mysql 的data,以及常用软件的配置文件也放到 aws ebs上
  5. 有重要的更改之后,一定要重新创建一个image,因为每一个instance 在启动之后都是全新的。
  6. ebs volume 需要和 instance 处于同一个地理位置。
  7. 写一个脚本,开机自动运行 associate ip 以及 mount ebs volume 以及 自动启动服务。

发表评论

把yahoo yql 当做 crawler 来使用

在我眼里,yahoo.com 是一个在技术上努力,并锐意进取的公司,从 yahoo.com 开放的众多服务就可以看得出来。 yahoo.com 的这些创意十足的技术人员是 yahoo 的最大资产,也是MS 当初对 yahoo.com 发出收购邀约的主要目标之一。当然yahoo.cn 就另当别论了。

yql 是 yahoo.com 推出的另一项重要的搜索api,yahoo.com 在搜索方面已经有了一些重量级的api,比如说 BOSS 以及 SearchMonkey。 我觉得 yql 对于开发者来说则是另一个惊喜的礼物,通过 yql 的api,开发者就可以通过类似于 sql语法的对internet 上所有的网络资源进行 “查询”。 “查询”的意思就是说,internet 上的所有网络资源相当于一个超级大的数据库 ,通过 yql 的语法,你可以查询到你想要的结果。

yql 的限制非常少,public data 的 access limit 是1000 req/hour, 对于普通的应用来说已经足够了。另外可以通过 yql console 来运行 yql 的测试, yql console 也是学习和了解 yql 语法的最好的地方。

对于yql 来说,有一个另类的做法就是把 yql 当做 crawler 来使用。任何一个website,只要它不禁止 yahoo 爬虫,那么从 yql 里面都可以得到这个website 公开的web pages。

前段时间,我想去抓 aibang.com 的数据,自己写了crawler,后来发现 aibang.com 把我的ip block掉了,于是给自己的crawler 加上了 tor proxy。这样的效果也不好, tor proxy ip 都不知道从哪来的,抓一个 aibang.com 页面都要 1 秒多时间。后来换成使用 yql,省时又省力,问题轻松解决了,因为yql 估计有一堆的服务器帮你去抓数据,aibang.com 还能把这一堆服务器的ip 都 block 掉? 小样。。

如果你要去抓aibang.com的数据,你的yql可以这样写:select * from html where url=”http://www.aibang.com&#8221;

如果你只需要网页的一部分数据,你可以给yql加上xpath 解析,比如:select * from html where url=”http://www.aibang.com&#8221; and    xpath=’//div[@id=”weatherUseInMapview”]’   。 这样就可以得到 aibang.com首页 的天气预报的详情了。

那么 yql 抓到的数据会不会是cached 的数据? 在我的实践中,yql 抓到的数据都是即时的数据,基本上没有cached。

yql现在已经成为我的工具箱里面的必备工具,希望它能对你也有帮助。

发表评论

在rails中使用 couchdb 以及 solr

随着项目的向前推进,有一些的问题浮现出来。比如说,有一个model已经有了很多属性,但随着需求的增加,还有不同的属性需要加到这个model里面去。通常的做法就是再往这个model对应的数据库表里添加相应的 column,有些属性有可能只是一部分的数据才需要,往数据库表里添加column的做法也会使得表结构复杂或者臃肿。boss 前些天给了一些key-value db 和 couchdb的资料,让我调研一下,看一看能否解决这些问题。

 key-value db 和 couchdb 这一类什么都能往里仍的数据库最近很火爆,但我觉得这一类数据库还没有具有成为解决关系数据库问题的“银弹”的能力。 在看了一些资料了和做了一些尝试之后,我觉得对于应用来说,固定不变和固定格式的数据适合于使用关系数据库来存储,对于不固定格式(或者说是弹性格式需要?)的数据可以使用couchdb来存放。

 如果只是得出这样的结论的就可以的话,那这篇文章就可以到此为止了。但是 boss 说,使用了 couchdb 以后,那我们原来需要使用 solr 来做搜索的那部分数据如果放到 couchdb 里面去,需要怎么修改来建索引? ok,那我还得继续努力。

介绍使用 couchdb 的rails 资料都是介绍如何在一个全新的项目里面来使用couchdb,如何对couchdb里面的内容进行全文搜索的资料也很少。 这里有一篇 ,不过我不想也不推荐使用这种方法,搜索还是应该交给搜索引擎来做,数据库做数据库的事情就可以了。couchdb-solr 使用了couchdb 的calllback 来将 couchdb 和 lucene(solr)结合的,但是需要编译安装它修改过的 couchdb,这样似乎也不可取。

我今天研究了一下,找到了一个稍微简单的方法,至少不需要改动现有的插件和太多代码。

要在rails 中结合使用 mysql ,couchdb 和 solr ,我们需要使用另外一个插件– stuffing。 stuffing 可以让你把一部分数据存储在 mysql,另外一部分数据存储在 couchdb,只需要加入 stuffing 的声明,很酷。

 把数据放到 couchdb 里面只是第一步,第二步需要把放到couchdb的数据做成索引,让solr 可以搜索得到。比如说我们有一个叫 Book 的model, Book 有一个tags 的属性需要放到couchdb里面,我们可以这样声明:

class Book< ActiveRecord::Base

  stuffing

  acts_as_solr :fields => [

  :title, :body,

  :tags,

  :facets=>[:title, :body, :tags]

  def tags

    self.stuffing_tags

  end

end

book = Book.new

book.stuffing_tags = “book, couchdb”

book.save

ok,就这样,tags这个属性就已经被存储到couchdb,并且也放进了 solr 的索引里面去了,就可以使用 Book.find_by_solr(“book”)来找到新建的 book了。定义 tags 方法的目的就是告诉 acts_as_solr 怎么找到 tags 的值。

如果我们放在 couchdb里面的数据是 hash,那么我们需要做的工作稍微多一点,但是原理是一样的。比如说一本书在不同的商店的价格是不一样的。那么我们需要想下面这样来定义 Book model。

class Book< ActiveRecord::Base

  stuffing

  acts_as_solr :fields => [

  :title, :body,

  :tags,

  {:dangdang_price => :range_float},

  {:zoyo_price => :range_float},

  {:chinapub_price => :range_float},

  ],

  :facets=>[:title, :body, :tags]

  def dangdang_price 

    self.stuffing_price[‘dangdang’]

  end

  def  zoyo_price

    self.stuffing_price[‘zoyo’]

  end

  def chinapub_price

    self.stuffing_price[‘chinapub’]

  end

  def tags

    self.stuffing_tags

  end

end

 book = Book.new

book.stuffing_tags = “book, couchdb”

book.stuffing_price = { ‘dangdang’ => 123.8, ‘zoyo’ => 120.5,  ‘chinapub’ => 110.6}

book.save

这样price的价格就以hash的形式存在 couchdb,并且可以使用 Book.find_by_solr(“dangdang_price:[100 TO *]“) 来找到相应的book了。定义这些多余的方法的目的就是把 price 这个 hash flatten。 这种方法对于多重hash 也可以使用,但是要做的工作也稍微多一点。如果你能有其他的方法,请告诉我。

Comments (1)

再见,2008

回过头来想,2008年对地球来说,这都算是不平凡的一年。对我来说,也许是转折的一年。

08年的差不多这个时候,我开始自学ruby 和 rails,差不多半年之后开始接手第一个离岸外包,再三个月以后离开原来所在的小公司,投入到另一个更小的小小公司,然后开始了在家 soho 的生活。我离开以后,原来的公司现在差不多已经分崩离析,坚持不下去了,这当然和我没什么大的关系。

 所谓小小公司,意思就是说人相当的少,基本上也就只能敏捷开发和敏捷管理。但幸好小小公司现在还没有被金融危机影响到,可以作为一个避风港,幸好我们都还有一些梦想(也就赚钱而已),幸好我还能有一股学习的冲劲。只不过发现soho的最大的一个坏处是,你拼命的想把工作在一天内做完,因为你随时都可以工作,但其实工作是怎么也做不完的。。。

 希望2009能更好一点,至少金融危机能过去,大家都有饭吃。 

再见,2008。 

发表评论

Older Posts »