2010年8月23日星期一

菲律宾前警察和现警察联合劫持及残杀香港游客

傍晚回家打开电视,习惯性转到香港台看新闻,头条就是旅行社在菲律宾被劫持。当时的消息还是比较乐观,说菲律宾警方称能够和平解决。连续报导了10来分钟,进入广告时段,回来后播放了10几分钟其它常规的新闻。然后突然就转入直播,而且传来消息说人质已经全部遇害。

当时我觉得不大可能,因为劫持人的诉求是复职,那么其劫持行为应该是为了引起公众注意,所以选择了在热门景点劫持外国旅行团,而且前面还是放了部分体弱妇孺,理当是一种谈判姿态的。

接着就是菲律宾警方开始行动。看到他们抡锤子的时候,我当时的感觉是,完了,人应该全部死光了,否则没理由这样行动的。

以我这么一个纯外行的人看来,除非确认人质全部死亡,否则就或者不行动,选择行动则需要迅雷不及掩耳强攻,在最短时间进入车厢击毙枪手,尽量不给枪手时间开枪伤害人质。但是菲律宾警察怎么干的呢?花了整整一个小时,用锤子抡了两个侧面的窗户、旅游车前门、正面挡风玻璃、车尾玻璃,每个地方都敲几下烂了之后就转移地方,这是在干啥?简直就是在劝枪手————你开枪吧,杀人吧!

说老实话,当时我看得目瞪口呆!

最后看到有人质活着跑出来,我觉得太幸运了。枪手看来心理素质极强(原本就是高级警官),而且还是有点人性,两者缺一不可,否则何以抵挡菲律宾警察的“劝导”。

补:

1、有报道称,有遇难者是被“特警”用锤子打玻璃窗的时候直接砸死的。回忆我看到的现场直播,有这种可能,起码是砸晕。因为在砸破的窗玻璃附近,窗帘飘起,可以看到有一个人在那里,但是不见有任何移动。

2、有报道称,枪手不是被菲律宾警察击毙的,而是人质反抗夺下枪支后击毙。我也觉得非常有可能,因为我当时就很疑惑,不见任何行动,为何枪手突然就死亡,而且尸体被塞出车门,所以也不可能是吞枪自杀。

2010年7月21日星期三

骗子新手段

接到一个电话:
-请问是太白电子科技有限公司的麦经理吗?
-是
-我是福田区工商局法制科的,现在统一要做企业的法制培训,blablabla……
-呃,哪里?
-福田区工商局法制科
-那怎么是一个浙江的手机打给我呢?
-我们这不是手机,是网络电话(挂断)

2010年5月5日星期三

查询条件子集判断的解决思路

王建硕的百姓网发了一道公开面试题。刚开始的时候觉得挑战很大,但是王建硕后面做了澄清,发现其实并不难了。

大体思路如下。本来想贴在王建硕的Blog的后面,结果杯具鸟,贴了几次都是500。

------------------------------

如果是处理QueryBuilder的话,那简单很多哦。其实这里面最繁琐的一步就是解析字符串格式的Query。其实就算是字符串形式的,如果每个AND和OR都有括号括起来的话,处理也不复杂。

我不认为tyler durden的“很难找到一个通用的方法”的想法是对的。这应该有通用解决办法的。

初步思路就是把queryA和queryB分别规整为一系列的原子条件的AND集合的OR集合。例如,将
(A<10 OR A>20) AND (B<10 OR B>20)
变换成为:
(A<10 AND B<10) OR (A<10 AND B>20) OR (A>20 AND B<10) OR (A>20 AND B>20)

为方便叙述,我们将A<10、B>20等称为“原子条件”,将原子条件的AND集合,称为“条件集”。将条件集的OR集合,称为“查询”。

要判断查询A是否为查询B的子集,需要将A的所有条件集都为B的子集。

要判断一个条件集A'是否为查询B的子集,只需要A'为B的任意一个条件集的子集。

要判断一个条件集A'是否为条件集B'的子集,需要A'的所有原子条件A'':或者在B'中没有相应的条目,或者B'中的相应条目的条件已经涵盖了A'',我相信这一步已经很容易做了。

-------------------------------------

写完了之后,发现已经有mikster的留言把上面这个过程用很数学的术语给描述过了。苍天作证,我是写完之后才看到那个留言的,绝对没有抄袭。 :-D

--------------------------------------

BTW,王建硕算是大牛了,怎么搞了这么囧的一个Blog Hosting啊。

2010年3月30日星期二

腾讯版Android QQ是个烂产品

今晚在cnBeta看到消息说腾讯发布了Android版QQ,马上上菜市场下载了一个。

心想腾讯磨蹭了这么久才搞出来的东西,应该不会差吧。结果大跌眼镜。

最大的问题,应该归类为Bug。在设置里面,可以设置接收或者屏蔽群消息,设置完了之后,所有的群都会变成一样的接收或屏蔽状态。单独的群可以设置个别的接收屏蔽设定。问题是,如果有任何一个群设置为接收,那么下次启动的时候(或者进入设置了之后退出之后),所有的群又都变成接收状态了。

当年PC版的QQ,是强制开机启动的,直到最近两年才在安装的时候让你选是否开机启动。而作为手机QQ来说,开机启动不能说更加有需要,但是应该也是很有需要的选项,这个版本的QQ反倒没有提供自动启动的选项。

另外,对于聊天记录,不能复制,不能点击里面的链接。

作为一个QQ号小于10200的QQ老用户,用过的QQ产品其实不算多,但是这个是我用过的最烂的QQ产品。入手XT800后先后从菜市场下载过近百个应用,这个绝对是最烂的,没有之一。

2010年3月8日星期一

Google Map API 国内地图偏移的解决

由于国内地图采用的坐标系统和国际通用的不一样,所以如果直接用GPS取得的经纬度来请求Google Map,会发现有偏移。CSDN上有个牛人找到了Google修正偏移的接口,完美解决了这个问题

在使用他所说的方法之前,为了解决地图偏移问题,找了不少资料,发现对引起国内地图偏移的原因有所误解,也就是说,其实不是以前一直以为的有关部门瞎折腾。

简单地说,地球不是一个完美的椭圆体,所以如何以经纬度及海拔来标识地球上面的一个点,与选择什么样的近似椭圆体是有关的。(外行表述,行家请指教)国际上比较通用的体系叫做WGS84,中国现在的地图则基本采用了北京54体系,另外国内还有一个西安80体系,看到资料貌似现在新建设的GIS系统还要采用一个2000年的标准。

一个国家采用自己的标准,也不是只有中国这么干,貌似现在有上百个这类的坐标系。坐标系之间是可以互相转换的。首先,要将一个坐标系的经纬度和海拔BLH这三个数据,根据选择的椭圆形的长径和扁率来转换成称为大地坐标的XYZ,然后使用另外一个体系的长径和扁率来将XYZ转换成新的BLH。所有的坐标体系所选择的椭圆形的半径和扁率都是公开的,包括国内的这些。

这样看起来貌似没问题,但是实际上通过这样的转换是无法得到正确的坐标的。因为各个坐标体系选择地球的哪个点来作为椭球的中心,以及坐标轴的方向,都不一样的。所以,在将XYZ转换成新的BLH之前,还需要对XYZ进行一次变换。外行的我不知道原因,只知道地球上各个点要进行变换所需要的参数是不一样的,而且是没法通过公式计算的。

其它的坐标体系会把变换所需要的参数公开,但是北京54和西安80则只公开了这两者之间互转的参数,原因是基于国家安全的理由。所以,世界上的GIS系统支持很多坐标系,但是就是没法支持这两个,也增加了国内搞GIS的人很多麻烦。

总而言之,国内采用自己的坐标系,不是特立独行瞎折腾,只不过……

2010年3月6日星期六

Android开发:在Camera Preview上叠加信息

自从买了XT800之后,对Android的应用开发热情暴增。最近想尝试做一个现实增强的试验。所以,需要在摄像头的预览画面上面增加文字或者图形信息。

摄像头的预览网上的示例很多,都是用一个SurfaceView来做容器。所以要往预览画面上面写字,最直接的想法,当然是从SurfaceView那里锁定一个Canvas来画东西了。但是马上就会发现这种方法是不行的,因为这个SurfaceView必须设成SURFACE_TYPE_PUSH_BUFFERS这个类型,也就是不自己管理buffer,这样才能让预览画面由摄像头自己管理,所以无法取得Canvas。

第二个思路,就是在用于预览的SurfaceView上面再叠加另外一个SurfaceView,用第二个SurfaceView来显示叠加信息。但是马上就会发现,此路依然不通,因为SurfaceView是没法设成透明的,叠加的信息显示出来了,但是预览画面却又会被遮盖掉。

冥思苦想了几分钟,找到了办法:用一个AbsoluteLayout来装预览SurfaceView,然后编程添加类似TextView等内容动态添加到AbsoluteLayout里面。

试验成功。下一步试验内容是获取罗盘状态和GPS坐标。

关键代码:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
layout=new AbsoluteLayout(this);
setContentView(layout);
surfaceCamera=new SurfaceView(this);
holderCamera=surfaceCamera.getHolder();
holderCamera.addCallback(new CameraCallback());
holderCamera.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holderCamera.setKeepScreenOn(true);
layout.addView(surfaceCamera);
layout.setOnTouchListener(new View.OnTouchListener() {
int i=0;
@Override
public boolean onTouch(View v, MotionEvent event) {
try
{
TextView tv=new TextView(Main.this);
tv.setText("x");
AbsoluteLayout.LayoutParams lp=new AbsoluteLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
(int)event.getX(),(int)event.getY());
layout.addView(tv,lp);
i+=10;
}catch(Exception e)
{
Toast.makeText(Main.this, e.toString(), Toast.LENGTH_LONG).show();
}
return false;
}
});
}