尽人事 听天命

从十几岁开始,思考人为什么要活着这个问题,很快这个问题的答案显得不那么重要,因为思考的结果直接导致我相信命中注定。因为我是单纯从哲学的角度思考这个问题,而不是因为自身经历而产生的厌世情绪,所以我觉得有必要说一下。注意不是宿命,不是命运,而是命中注定,我觉得这几个词之间是有微妙的差别的,宿命与命运是一个范畴,而命中注定,是对宿命观的一个具体定义。

从微观物理学的角度上来说,一切物理现象都是有规律的,虽然在量子物理的层次上,有诸如测不准、不可知、不连续、等现象,但这都只能说明人类认知的极限,不能否定“一切物理现象都是有规律”的这一定律,爱因斯坦说“上帝不掷骰子”。人类可能以为自己的行为是有主观能动性的,不受规律限制的,但事实上,生物学基于化学,化学基于物理学,我们人类的一切活动都已经由最微观的粒子所决定了。

再从宏观系统论角度来分析。一个微观系统很难对一个宏观系统产生巨大的影响,除非这些微观系统体现出惊人的一致性。比如太阳系的活动很难影响到整个银河系,但反过来则影响很大。而人类社会看起来是一个复杂的系统,但依然是符合这种宏观系统与微观系统的制约规律的。

人类社会目前还是局限于地球这个环境的,而且目前人类也是无法操控气候的,人类社会系统无法过多的影响地球的气候系统,但地球气候系统的细微变化都会对人类社会产生巨大的影响。人类的生死往往只在瞬间。

人类社会由各种政体国家所统治,由几大主流的价值观所统治,人类的经济活动和思维模式都受这些大系统的影响。我们都是被各种经济活动和思潮变迁裹挟着在前进。人类社会的变迁往往只在一个很短的时代内完成。

人类社会资源的分配方式,是由下层聚集到上层,并由上层分配到下层的一个循环。你可以看出这种资源分配方式是多么不合理了吗?你获得的资源,与你付出的努力关系很小,而只与你所处的资源分配层次关系最大。而决定你分配层次的往往只是一两个瞬间:出生、升学、第一份工作、面试的表现。这点 赵劼 举了很多例子。

你的伴侣会陪伴你的一生,影响你很多的决定,而你和你伴侣的相识只在某一个瞬间。

我们的人生由太多的瞬间所决定。而这一瞬,有太多的巧合,这种巧合其实都是命中注定。

如何正确处理命中注定这一观点:

你努力了,不一定会成功(你可以随意定义什么是成功),但是不努力,有很大可能不成功。中国古人是很早认识到天命的,六个字概括的太好:"尽人事,听天命"

哲学


web前端脏乱差及其解决之道

这是一个软件工程问题

先吐槽一下,遇到许多所谓“软件工程师”,根本没有“软件工程”的概念,make,ant,持续集成,自动化测试,一概无视,这样的人只能称码农,不能叫软件工程师。 很多牛逼的软件工程师喜欢自称程序员,导致很多菜鸟认为会写程序就足够了,殊不知“programmer”、“coder”是牛人们的谦称————不懂软件工程之人不足与之论代码。

Web前端脏乱差

Web前端长期以来很混乱,虽然不断的有人用各种框架,工具来改善前端开发过程,web前端依然让人感觉脏乱差。究其原因有三: * javascript语言层面缺乏包机制。这是requirejs之类所试图解决的问题 * web前端包管理机制问题复杂,不仅需要考虑js,还要考虑css和html。这是bower试图解决的问题 * 有合并、压缩的需求,虽然有很多工具很好的完成了压缩的工作,但合并一直缺乏优雅的方案。

前端社区割裂

基于前面说到的一些问题,导致社区产生了大量风格迥异的js代码。这些代码也许可以一起很好的工作,但将错就错的行为让社区更加混乱。

这过程中产生了一些子社区,比如jquery,这导致了javascript社区的分裂。 Argular试图重新定义前端开发的整个流程,google一直在尝试让web前端的开发过程变得像传统软件开发一样清晰,比如GWT和Dart。 Argular取得了一定的成功,但依然有不少web工程师对Argular比较抵触。 所有试图以框架来解决web开发问题的,最终的结局要么是消亡,要么是割裂。

解决之道

正确的选择只有一条,就像其他编程语言一样:

  • 统一社区风格, 利用社区的力量。
  • 不应该让整个社区依赖某一个框架,我们只需要制定行业标准。

目前有些工具在解决这些问题:

  • Bower 是包管理工具
  • grunt是构建工具
  • CMD, AMD的一堆工具
  • component则是既包含包管理,也包含简单的构建,同时component还是一个CMD工具。

我个人认为component是目前最好的解决方案。因为 component 包含了 bower + grunt + requirejs 的主要功能,而我们没空去学那么多乱七八糟的工具。

有人可能会问,component的存在是否也会造成前端社区的割裂?component要做的不是框架,而是社区标准,所以component的存在不会造成社区的割裂,只会让社区更加繁荣。

component 社区虽然也可以兼容jquery这样的框架,但这不是component所推荐的做法。component的风格是大量的小型的库,比如superagent, eacape-html, dom,每个库只做一件明确的事情。

后记

感谢TJ holowaychuk,给我们带来了太多美好的东西。不过自从TJ转投Go语言社区后,似乎是被Go社区"从语言层面解决软件工程问题"的哲学所感染,给component的发展带来了一些不确定性。目前component的官方网站component.io已经无法访问。TJ 在component的一条issue中表达了自己的一些观点:“遗留的npm/browserify是最坏的东西,说实在的Go的方法好多了,只要ES6的module loaders可以玩了。Browserify最终会玩完,所有的都会哈哈,长期来看,他们都不管用,构建一点都不好玩”

原文

The rest of npm/browserify is mostly bad stuff, a Go approach would be much better IMO, once ES6 module loaders are in play. Browserify will eventually die out too, they all will haha, long-term none of them make sense, builds are no fun

web, 前端, 软件工程


redis的list类型控制随机性分布

有这样一个需求: 1. 随机的给用户1篇文章 2. 最新的文章有更大的几率被随机到 3. 被随机到之后,文章被随机到的几率降低 4. 同一文章大约可以被最多随机到5次 5. 在文章较少时,1操作很多时,系统依然可以正常运行

实现:

# 新文章加入系统时 插入5份
LPUSH articles id1
LPUSH articles id1
LPUSH articles id1
LPUSH articles id1
LPUSH articles id1
# 根据随机数x取一篇文章, 结果为idx, x < N, N代表最新的N篇文章
LINDEX articles x
# 将x从articles 移除 1份
LREM articles 1 idx
# 将idx从右方插入
RPUSH articles idx

redis


修复mysql 1449 NO_SUCH_USER 错误

权限一律正常。原来是trigger或view需要在分配好权限后,重新生成一遍,改DEFINER=username

mysql


functional programming and sprite system

How to make a sprite system with functional programming.

function + data.

数据+实现,配置+接口,是一种编程模型。OO在某种形式上,也是一种数据+实现的编程模式,但他将2者耦合在一起。而模板+数据,则是一种更加解耦的模式。

{
    img: img,
    rect:{x,y,w,h}
    screenRect: {x,y,w,h}
    children: [
        {
            rect:{x,y,w,h}
            img: img,
        }
        {
            rect:{x,y,w,h}
            screenRect:{x,y,w,h}
            frame: 0
            frames: [
                {img: img1},
                {img: img2},
            ]
        }
    ]
}

render

scale

animation

tween: action: move rotate scale

game,html5,


小游戏1024的AI数学模型

游戏规则

1024 是一个近期比较流行的小游戏,也有称之为2048。游戏在一个4x4的方格(grid)中进行,方格中会在随机的一个空白位置填上一个数字2,玩家可以选择将所有数字向上、向下、向左、或向右的某一方向移动,所有数字将往这一方向移动,如果数字碰到了边界或一个不相同的数字,则停止移动,如果碰到了相同的数字则这两个数字将会合并为两数之和。如果移动之后局面未有任何改变,则此方向禁止移动。在玩家进行了一次移动后,方格中会再随机的产生一个数字,如此循环,直到4个方向都不可以移动则游戏结束。玩家的目标是尽可能的合成更大的数字。

2 2 0 0           4 0 0 0
4 0 0 0           4 0 0 0
0 0 0 0  向左移动 0 0 0 0
0 0 0 0           0 0 0 0

2 2 0 0           0 0 0 4
4 0 0 0           0 0 0 4
0 0 0 0  向右移动 0 0 0 0
0 0 0 0           0 0 0 0

2 2 0 0           0 0 0 0
4 0 0 0           0 0 0 0
0 0 0 0  向下移动 2 0 0 0
0 0 0 0           4 2 0 0

2 2 0 0           2 2 0 0
4 0 0 0           4 0 0 0
0 0 0 0  向上移动 0 0 0 0  局面未改变,禁止此方向
0 0 0 0           0 0 0 0

   2    4    8   16
  32   64  128  256
  64    2    8 1024  任何方向都无法移动,终局。
   2    4   16    8

目标

笔者尝试通过AI来解决这个问题以得出尽可能大的数字。在开发过程中设计了多种数学模型来求解这一问题,希望借本文与大家分享数学建模的一些思路。

我的AI算法使用的是alpha-beta pruning。Alpha-beta pruning算法常用于博弈程序的AI,比如象棋、国际象棋、五子棋等。其基本思路与Minimax search相似,通过对当前局面及其分支的评分,得出最优解的算法,只是通过剪枝的算法大大降低了算法的复杂度。1024这个游戏也可以理解为一个博弈游戏,玩家向某方向移动,电脑落下一个数字,这是一个玩家与电脑博弈的过程,玩家希望得出最大数字,电脑则是尽可能的让这个数字出现在玩家最不希望它出现的位置(实际游戏过程中,这个数字的出现位置是随机的)。

Alpha-beta pruning算法是非常依赖于启发函数(Heuristic)的,启发函数是对于一个局面G的优劣的评估值,记为h(G),h(G)越大,代表局面越好,h(G)越小代表局面越坏。Alpha-beta pruning的目标是做出当前局面G下的最佳决策,依据于一定深度的子分支的评价结果。因为深度有限且部分分支被抛弃,所以alpha-beta不能保证搜索到的结果是最优的,所以启发函数h(G)不仅用来评价局面的好坏,也用于引导搜索的过程。

本文要讨论的即是关于1024游戏的启发函数h(G)的设计。

数学模型

我们都知道数学是什么,但什么是数学模型?我们说铁比棉花“重”,这不是数学模型,而我们说铁的密度更大,而密度=质量/体积,这就是数学模型。我们说某个人速度很快,这不是数学模型,速度=距离/时间,他的速度是10米每秒,这就是数学模型。我们说今天阴天,可能会下雨,这不是数学模型,而我们说今天下雨的概率是P(下雨|阴天),这就是数学模型。

当先贤们创造经典力学的时候,他们是在对我们的日常知识建立数学模型。比如你说推一个轻的车比推一个重的车更容易,但如果你说,F=ma,那么你就是牛顿。

顺便说一句,我认为数学教育的目标应该是建立数学模型,而不是解题。

关于1024这个游戏,我们说局面A比局面B更好,那么怎么样对一个局面的好坏建立数学模型呢?h(G_A) < h(G_B) 则认为局面B比局面A更好。

2 4 2 8     2 4 8 16
4 2 4 4     2 2 4 8
2 4 2 4     4 4 8 4
4 2 0 0     0 0 4 8
   A           B

最大值模型

基于游戏的基本目标,我们希望尽可能的合成更大的数字,我们可以很显然得出一个数学模型:当局面G里出现的最大数字越大,则代表局面越好。即:

h(G) = Max(G)

假设G中目前的最大数字是256,基于此模型,AI将会尽可能的将这个数字合成到512,然后将512合成1024,然后是2048。看起来是很合理的。但实际测试中发现了如下的局面:

4   2   4   8
2   512 16  2
64  2   32  4
2   8   4   2

为什么发生这种局面?因为我们的AI过于急功近利了,因为最大值模型。就像我们设计了一个象棋程序,直接吃掉对方老将。。。

algorithm, mathematics


程序員的自我管理

一位39歲的程序員在Stackexchange 上自爆隨著自己經驗的豐富,自己完成項目和任務的時間反而越來越長。 這引起了許多程序員的共鳴。

他描述了一些自己遇到的狀況。當他決定開始著手寫一段代碼的時候,他會開始考慮很多問題。 諸如:權限、鎖、併發、框架,等等。

有許多人和我有相同的體會,編程中我們有大量的時間花在了變量名的選擇,甚至項目名稱的確定上。

此外還有許多人有這樣的怪癖——他們始終對IDE不滿意。他們花費大量的時間選擇他們順手的IDE。 甚至自己動手編寫插件。(比如我,時常折騰我的Vim配置,花去了大量的時間,最近考慮轉向Atom。)

此外關於程序員的TODO管理,也是是一個很大的問題。

A:請說一個關於程序員的笑話。B:TODO。

程序員最大的謊言——TODO。

總之,程序員除了真正的思考和動手去實現自己的項目外,還需要花費大量的時間在各種瑣事的管理上。 這些瑣事主要是代碼質量控制、實現方式的選擇、工具和框架的選擇、功能和bug以及重構等任務的管理。

一個重要的客觀現象!

當我們說到程序員任務delay的問題時,有一個重要的現象:

一個優秀的程序員在按照產品經理的要求下進行工作的時候可以按時完成任務。 他們甚至在完成工作之餘還有時間做點自己的事情。

但當他們想做點自己的事情時。他們往往會delay,甚至無法完成自己設定的任務。 他們的吸引力往往會轉移到其他的事情上。

這種delay和fail的情況有時也會發生在那些由優秀程序員擔當管理者的項目上。 這些程序員往往在他們擔任管理者的同時,也同時從事編碼工作。

(我無法提供數據來證明以上的普遍性。這只是一種基於自身和觀察的經驗。 希望有人可以告訴我一些證據以上現象是非常少的個案。)

以上現象似乎說明程序員缺乏足夠好的自我管理能力。但這在邏輯上是說不通的, 程序員們是不會相信項目管理比編寫程序更加複雜這種事的。從某種意義上說,編程 本身就是非常複雜的管理工作

可能的原因

  1. 程序員實在是太忙了。他們沒時間做任務管理。

對於一個——剛打開編輯器就發現了一些不順手的地方,於是著手去編寫一個插件來滿足自己的需求。 隨後將自己的插件發佈到網絡與大家共享——順便看到了他人的貼子,於是有了一些感慨—— 決定寫一篇博客記錄自己想法——的人來說,你覺得他還會有多少時間來做別的事情呢?

  1. 程序員是興趣驅動的,而不是目標驅動的。

這是很普遍的一點,大多數的程序員選擇編程這份工作是因為愛好。 對於一個非目標驅動的人來說,無法完成目標就再好理解不過了。

  1. 程序員過於追求完美。

這一次,程序員決定改過自新,不再東搞西搞,專心的完成目標。但他發現問題比他想象的複雜。 他無法接受那些產品經理們所建議的“設計上的臨時解決方案”代替“技術上的徹底的解決方案”。

沒有階梯我們無法攀登,而沒有產品的過渡,我們甚至無法生存。

done is better than perfect

解決之道

如何解決這個問題,每個人可能有不同的見解。

  1. 目標驅動,平衡興趣,制定時間分配計劃。

目標與興趣之間需要平衡,他們是相互裨益的。單純的為完成目標而工作,工作會變得乏味。 只是追求興趣,也並不能學以致用。

  1. Push。

只是制定計劃是沒用的。程序員必須要有人Push,這個人可以是你的夥伴,也可以是你的用戶。 他們的要求,會對你有很大的推動力。如果都沒有,我們可以創造一個工具來Push自己,它可以 用消息、統計等方式來強化你的目標概念。

  1. 始終以里程碑版本為目標。

工具

  • 自动化番茄钟

    • 编辑代码,开始计时
    • 离开编辑器,AFK
    • 提交代码,计时完成
    • 统计
    • 工作时间(使用编辑器的时间)
  • 可以被版本控制的目标

    • 非excel
    • 非online數據
    • 文本存儲
  • 腦圖

    • Tree map
    • TXT or MarkDown
  • TODO

  • 里程碑

    • 分支開發

management


全端工程师一词出现的原因

晚间在微博上看到@左耳朵耗子 的一篇微博, 讽刺自称全端工程师的人,原文如下:

有些人啊,自从用了Node.js 后,发现可以用Javascript通吃前后端,于是就号称自己是全端开发。我想说,我在十多年前学Java的时候,那时Java通吃所有端,无论是CLI/GUI的,还是Web端和Flash啥的,包括什么Win/Linux/Unix平台,手机端、嵌入式的统统吃掉。就这样,那时都没人说自己懂Java就是全端开发。

原本我对这个词既并无太大感觉,觉得这是个中性的偏正面的词。但看了这篇微博和它的诸多评论之后发现,自视甚高的程序员们对这个词是很反感的。我的感觉是:What?难道对知识的渴望和不被规矩所束缚不正是黑客精神所在吗?

很多人反对的并不是全端工程师,而是全端工程师这种逼格过高的称谓。就像耗子所说的,当年他如何如何也未敢自称全端。亦有人认为全端是一种营销手法,当年不这么说是因为当年不懂营销,不懂炒作自己。

持以上观点的诸君都没有理解这个词出现的原因。私以为全端工程师一词目前出现是有原因的。是Web开发技术进化到今天必然所产生的一个结果。

在Web开发的洪荒时代,是不区分前后端的。无论是CGI,JSP,ASP还是PHP,都是前后端耦合的。也就是耗子君所说的用Java通吃所有端的时代,那时不叫全端工程师,而是叫Java软件工程师,但那时的Java软件工程师也是要写前端的,虽然一般Java工程师写的前端水平有限。

PHP工程师是真正的全端工程师,因为这门语言的应用领域就是web。他们的前端水平是高于Java工程师和.Net工程师的,他们对后端的追求也与Java工程师不同。因为PHP大多为互联网服务,而JAVA大多为企业服务。

所以那个时代是不需要有全端工程师这样一个词的,大家只会说PHP工程师,JAVA工程师,就已经默认了他们前后端都懂点了。

但随着Web 2.0的兴起,前端越来越受重视。于是前后端开始分离。这时才真正有了前端工程师一词。非常有趣的是,这一次不再是以一门编程语言来命名这一类工程师,而是以它的开发场景来命名。当然我们也可以叫他Javascript工程师,这其实是他们最合适的名称。但由于web开发中的HTML、CSS部分比重也不小,Javascript不能涵盖所有前端内容。于是他们应该叫web前端工程师,而不是Javascript工程师。

然而nodejs的出现,将javascript带出了浏览器,它使得javascript也可以开发后端。同时,nodejs也深深的影响了前端的开发过程。越来越可以感受到,前端开发的主体正是javascript。而此时,有许多的前端程序员开始逆袭后端。这时候,他们是最有资格说自己是“Javascript工程师”的时候。

然而,尴尬的事情出现了。Javascript工程师们发现他们不能像PHP工程师们自称自己是PHP工程师那样自称自己是Javascript工程师。虽然他们都是前后端通吃的,但是人们从字面上却无法区分他们。大部分人会误解他们,认为Javascript工程师必然是前端工程师。这很显然对于也了解后端的Javascript工程师是不公平的。

于是,为了避免被误解,沿袭“前端工程师”一词的传统,“全端工程师”一词出现了。然而他们又再一次被人们所误解。

所以,这个词基本上是一个中性词,可能略带向分工过于细化的软件行业挑衅的色彩。这可能会让已经适应了分工细化的工程师们无法接受。但无论分工细化是否是更高生产力,作为一名程序员,应该不设限的对知识的充满渴求,亦不应嘲笑他人用不设限的方式来定位自己。

注:我通常自称Nodejs程序员,因为我的前端能力还不够,正在向“全端工程师”努力。 注:本文中所谓“全端工程师”特指Web场景下的全端工程师,而不包括移动端。

web


適合中國開發者的國外VPS

爲什麼我們需要一個國外VPS

  • 翻牆
  • 不想備案
  • 服務好

缺點

  • 速度慢
  • 價格高

可以用GAE嗎?諸多不便,限制你的開發環境,而且不能ssh。此前使用的是Linode,但是一直速度比較慢。現在福音來了

吐血推薦Digital Ocean

優點

  • 簡便易用,界面非常的清爽。
  • 全SSD硬盤,速度快。
  • 流量足。
  • 按小時計費,不需要包月,用多少扣多少。
  • 隨時可以備份你的系統,甚至可以跨機房傳輸你的備份。手動備份是免費的。你可以隨時恢復你的備份。
  • 價格便宜,最低每月只需要5美元。
  • 多種操作系統可供選擇。
  • 最近新增了新加坡機房,國內訪問速度很快,只有100多毫秒的延遲。

省錢技巧

請按照如下順序操作

  • 第一步 點擊這裏進入digitalocean註冊帳號
  • 第二步 使用你的信用卡或Paypal完成至少10美元的支付。
  • 第三步 搜素 digital ocean promo code 2014 找到一個推廣碼
  • 第四步 在Billing中的最下方輸入推廣碼,可以額外獲得10美元。

VPS


Android UI 动画

UI动画不同于游戏动画。我们不能把全部精力放在动画上,因此必须要让开发动画的成本降到最低。作为一个懒人,必须要搜索一些现成的库了。

ListViewAnimations 列表动画,很多常用动画,功能强大

Android flip 翻页动画

Free Flow 扁平化块状布局,支持动画

ActionBar Pull To Refresh 和动画无关,但不知道为什么想记在这里。

另外动画硬件加速,可以支持应用级,Activity级,Window级,View级。

接下来要看看代码,对自定义View和Animation深入了解一下。

Android animation UI


Java包管理和構建工具

雖然不喜歡JAVA,但是想學Android,還是要重新撿起來它。但是已經習慣了npm如此方便的包管理工具的人已經無法適應沒有npm的生活了。

N年前,JAVA的構建都是用Ant進行的,但Ant只是專注於構建,並不做包管理。後來是Maven,maven既有構建工具,也有包管理(依賴管理)的功能。但是Maven的pom.xml寫起來實在冗長,不想寫。

於是重新去瞭解了一下,發現JAVA領域也已經產生了一些新的包管理和構建工具了。Gradle和Ivy。

Ivy 是Maven之後的又一個包管理工具。而Gradle則是基於groovy語言開發的一種java構建的DSL(領域專用語言 Domain-specific language)。

Ivy安裝前需要安裝Ant,Ivy本身是Ant的一個子項目。與Maven既做構建又做依賴的方法不同,Ivy只做依賴,而構建交給Ant來做。我比較喜歡Ant + Ivy這種模式,Maven過於耦合。 我們的Java項目下應該存在一個build.xml和一個ivy.xml,分別用於描述Ant構建過程和依賴。

使用Ant自动安装Ivy

Ant自动安装Ivy

<project name="demo" default="resolve" xmlns:ivy="antlib:org.apache.ivy.ant">
    <property name="ivy.install.version" value="2.2.0" />
    <condition property="ivy.home" value="${env.IVY_HOME}">
      <isset property="env.IVY_HOME" />
    </condition>
    <property name="ivy.home" value="${user.home}/.ant" />
    <property name="ivy.jar.dir" value="${ivy.home}/lib" />
    <property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />

    <target name="download-ivy" unless="offline">
        <mkdir dir="${ivy.jar.dir}"/>
        <!-- download Ivy from web site so that it can be used even without any special installation -->
        <get src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar" 
             dest="${ivy.jar.file}" usetimestamp="true"/>
    </target>

    <target name="init-ivy" depends="download-ivy">
      <!-- try to load ivy here from ivy home, in case the user has not already dropped
              it into ant's lib dir (note that the latter copy will always take precedence).
              We will not fail as long as local lib dir exists (it may be empty) and
              ivy is in at least one of ant's lib dir or the local lib dir. -->
        <path id="ivy.lib.path">
            <fileset dir="${ivy.jar.dir}" includes="*.jar"/>

        </path>
        <taskdef resource="org/apache/ivy/ant/antlib.xml"
                 uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
    </target>

    <!-- ================================= 
      target: resolve              
     ================================= -->
    <target name="resolve" description="--> retrieve dependencies with ivy" depends="init-ivy">
        <ivy:retrieve />
    </target>

</project>

ivy.xml

<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0">
    <info organisation="org.apache" module="hello-ivy"/>
    <dependencies>
        <dependency org="commons-lang" name="commons-lang" rev="2.0"/>
        <dependency org="commons-cli" name="commons-cli" rev="1.0"/>
    </dependencies>
</ivy-module>

ivysettings.xml

Gradle

Gradle的職責是自動化構建,它同時支持Maven和Ivy包管理,甚至Ant的任務,比如這樣

build.gradle

task hello << {
    String greeting = 'hello from Ant'
    ant.echo(message: greeting)
}

task check << {
    ant.taskdef(resource: 'checkstyletask.properties') {
        classpath {
            fileset(dir: 'libs', includes: '*.jar')
        }
    }
    ant.checkstyle(config: 'checkstyle.xml') {
        fileset(dir: 'src')
    }
}

Java和XML是我最不喜歡的兩個東西,gradle可以讓構建不再是一堆雜亂冗長的XML了,而變成了一段優雅可讀的文字,很酷。但如果項目不是很大,構建不是很複雜,我覺得Ant+Ivy足夠了。 而維護一個複雜的構建過程時,Ant的build.xml一定會越來越亂,到那時,再切換至gradle不遲。

java build tools


About APK

APK是一種很不安全的格式,它很容易被反編譯和二次打包。

簽名 apk的簽名是不需要第三方驗證的。開發者自己管理keystore。

Odex 將APK中的classes.dex文件優化爲一個單獨.dex文件存放,原來的calsses.dex保留。可以提高App加載速度。是ROM中攜帶的一種功能。一些ROM沒有這個功能可以通過工具實現。

zipalign 可以讓APK資源被訪問速度更快,需要在簽名打包爲APK之後進行。因爲APK就是ZIP文件,也就是說讓ZIP文件讀取更快。

APK反編譯工具有很多,apk2java,dex2jar,jdgui,jad。比較好用的有apktool。還有圖形化的工具Androidfby。

Proguard 是class混淆工具,很久以前就有。但這也只是能夠提高略微的提高一些破解難度而已,作用不大。

Java bytecode,動態加載字節碼,這種方法也可以提高一定的破解難度。或者是使用ClassLoader(DexClassLoader、PathClassLoader)來做文章,將class加密,用自定義ClassLoader加載。

JNI 將部分代碼用c編寫,編譯成so文件,這種方法破解難度略大。

僞加密等方法上傳市場不支持,因爲市場需要解包檢查權限。且4.2版本後不支持這種方式。

可以看出,大部分的工具如proguard、jad、JNI等都是傳統的java技術,此外就是Dalvik的dex文件格式和zip相關的工具。

Android


Karam:多瀏覽器平臺的測試工具

nodejs讓js脫離了瀏覽器,它的包管理工具npm讓js代碼能夠更好的分享,此後前端開發因此產生了巨大的變革。

前端開發最痛苦的過程莫過於跨瀏覽器測試了。我一直期盼有一種更好的前端測試方案,當然不只是我這麼想。

ArgularJS團隊在開發過程中希望有一種更好的測試方案,他們定義了3條理想的測試工具應該具備的特點:

  1. it('should be fast')

它(‘應該很快’)

  1. it('should use real browsers')

它(‘應該使用真正的瀏覽器‘)

  1. it('should be reliable/stable')

它(’應該是穩定的‘)

在2012年11月27日,google發佈了博客Testacular-Spectacular Test Runner for JavaScript 介紹他們所開發的測試執行器(Test runner)Testacular,之後他們將此項目改名爲Karma。

安裝Karma

npm install karma-cli -g
cd projecthome
npm install karma
karma init

blabla, 讓我們跳過這一部分吧,直接給大家介紹最佳實踐。

最佳實踐

安裝yeoman, grunt, karma

sudo npm install yo -g
sudo npm install generator-argular -g
sudo npm install grunt-cli -g
sudo npm install karma-cli -g

創建項目

mkdir /path/to/project
cd /path/to/project
yo argular

安裝一些測試模塊

npm install karma-jasmin --save-dev
npm install karma-chrome-launcher --save-dev

執行測試

grunt test

增加其他瀏覽器

編輯karam.conf.js將browser改爲 js browsers:['Chrome', 'Firefox', 'Safari']

安裝其他的launcher

npm install karma-firefox-launcher --save-dev
npm install karma-safari-launcher --save-dev

再次執行測試

grunt test

web, 前端


编写atom插件

Atom 是github开发的编辑器,号称21世纪hackable编辑器。近日对其hack了一下,增加了一个命令行。

Atom的View系统很不错。

顺便学会使用licecap录了个屏。http://www.cockos.com/licecap/

接下来的目标是可以打开多终端。

UPDATE: 2014-03-22

多终端已实现,apm操作不慎,版本号bump到了1.1.0


靜態網站生成器

靜態網頁依然應用的很廣,但是開發一個靜態網站並不像想象的那麼簡單,快速,易於維護。

搭建慢。首先我們需要搭建項目的結構,引入我們需要的js,css,layout文件。

復用難。也許同樣的網頁我們之前已經做過一個,但當我們需要再做一個的時候,我們還需要從頭再做一次。如果我們直接複製粘貼此前的代碼到新項目中, 對代碼的合併,網站名稱,logo等信息的修改,刪除不需要的代碼,要花去我們很多的時間。一個網站下的多個頁面在結構上應該是復用的。

維護繁。對於一個已經完成的靜態網站,當我們想要修改它的時候,也並不是那麼簡單。比如我們要修改一個樣式,運氣好的話我們只需要修改一兩處css即可, 運氣差的話我們可能要修改DOM結構,但同一類頁面元素的DOM結構是分散在很多地方的,比如contact頁面,about頁面,某個landing page。 這就讓我們的代碼變得難以維護。

如果我們對靜態網站做一個總結的話,一般來說包含以下內容。

  • lyaout 網站的基本外觀框架。
  • partial 網站的常用局部組件。
  • data 網站基本配置,如標題,logo,base url,等。
  • pages 幾個頁面,比如about,contact。
  • posts 很多文章。

於是靜態網站生成器(static site generator)產生了。

現在比較常見的靜態網站生成器: * jekyll Ruby 實現,github支持,插件豐富,支持諸如tag,分類,本博客使用的就是jekyll。

  • harp http://harpjs.com

  • hexo http://zespia.tw/hexo

  • docpad docpad.org 基於coffeescript

  • assemble assemble.io

  • cabin] cabinjs.com

  • Yeoman yeoman.io nodejs環境。yeoman不能算是一個靜態網站生成器,你可以叫它項目生成器。它可以生成諸如webapp,argularjs,assemble的东西。

我的選擇 Yeoman + x,Yeoman 的設計是面向開發者的。

對於x的選擇,必須是nodejs的,從github關注量來看,docpad最多。但hexo和assemble产生较新,hexo关注人相对更多,看上去不错。

yeoman + hexo 計劃用這種方式來實現項目主頁,Landing Page。

web


尼爾森F模型

尼爾森F模型,是根據眼球追蹤技術的實驗數據得出的結論,即人類在瀏覽網頁時通常遵循先橫向再縱向再橫向的模式。

對這種模式的理解在提高網站轉化率方面非常有意義。

F-Shaped Pattern For Reading Web Content by JAKOB NIELSEN on April 17, 2006


开源语音识别引擎

大部分的语音识别引擎是收费的,或者是闭源的。google speech API不适合做语音控制系统,只适合识别日常语言。julius是一个日本人开发的语音识别引擎,GPL协议,看起来不错,决定研究一下。

今天花了很多时间折腾atom,是github推出的编辑器,可以方便灵活的编写插件。非常希望可以用说话来编程。折腾了一些,接触了如下东西。

  • sox (with flac format) 一个CLI程序可以录音。
  • node-speakable 录音并调用google speech API。
  • node-julius 顾名思义,node调用julius API。还没有使用。


遷移svn代碼到git

很多時候我們需要將svn代碼遷移到git。比如從visualsvn遷移到gitlab, 在此過程中你通常需要刪除一些垃圾文件,修改你的committer名字。

克隆svn代碼:

git svn clone svn_url

刪除不需要的文件

git filter-branch --tree-filter 'rm -rf node_modules'

刪除空的提交

git filter-branch --commit-filter 'gitcommitnonemptytree "$@"' HEAD

gc

git gc

如果你需要修改你的commiter或author名字

#!/bin/sh

git filter-branch --env-filter '

an="$GIT_AUTHOR_NAME"
am="$GIT_AUTHOR_EMAIL"
cn="$GIT_COMMITTER_NAME"
cm="$GIT_COMMITTER_EMAIL"

if [ "$GIT_COMMITTER_EMAIL" = "your@email.to.match" ]
then
    cn="Your New Committer Name"
    cm="Your New Committer Email"
fi
if [ "$GIT_AUTHOR_EMAIL" = "your@email.to.match" ]
then
    an="Your New Author Name"
    am="Your New Author Email"
fi

export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'

添加git remote庫並push

git remote add origin git_url

git push -u origin master

重新克隆一個乾淨的git庫

git clone git_url

完成。

git, svn


LocalStorage的异常处理

当达到localStorage容量上限时,按照标准描述会抛出 QUOTA_EXCEEDED_ERR. 但这个 QUOTA_EXCEEDED_ERR 到底是什么?一个常量?一个字符串?各浏览器的实现却不一样.

所以我使用了以下简单的方法来处理这个异常。

try{
    localStorage.setItem(key, value);
}catch(e) {
    localStorage.clear();
}

web, html5


你需要知道的Linux命令

  • grep
  • find
  • sed
  • xargs
  • awk
  • tar
  • vi
  • shell and shell scripts
  • top
  • account and group management commands
    • /etc/passwd
    • /etc/shadow
    • /etc/group
    • /etc/gshadow
    • ...

Linux高級命令詳解

linux


通用的項目文件結構

在項目開發過程中經常會因爲“應該將某個文件放在哪個文件夾下”,以及文件夾應該叫什麼名字這種問題而糾結。在經歷一次次痛苦糾結後,決定整理一個通用的項目文件結構。

/root
|- README ( LICENSE etc)
|- Makefile ( Gruntfile.js Dockfile etc)
|- /build (if you have complex build scripts)
|- /deps (node_modules, bower_components)
|- /test (test cases)
`- /src
    |- example.conf (example config or default config)
    |- /res (public resources, pack to client)
    |  |- img
    |  |- i18n
    |  `- ...
    |- /etc (miscs)
    |- /utils (utils depends nothing, reuseable)
    |- /core (engine, framework part, depends on utils, reuseable)
    |- /models (or services, talking to data and lowlevel interface)
    |- /routes (handle client request, most use in HTTP, sometimes it called `commands` in CLI or socket program.)
    |- /actions (controllers, UI delegates)
    |- /views (templates, UI, etc)
    `- /helper (like utils, but it is highly relatated with /core /models /actions /views.)

programming, node.js


Etag与Last-Modified以及浏览器永久缓存的比较

Etag 和 Last-Modified 的功效类似,但是Etag出现较晚。

Last-Modified 适合静态文件。

Etag 适合动态内容的变更。

永久缓存。。。这只适合类似图片、视频等内容。对js,css等静态文件可以通过加版本号的方式来永久缓存之。

xxx.js?etag=12345 这种方式来永久缓存

web


For each files in the Makefile

在构建项目时,时常需要遍历某个文件夹下的文件,按特定的方式将其预处理,变为一个新文件。

我们可以为此写一个脚本,负责遍历文件夹,处理文件内容,输出文件内容。

可以看到stackoverflow上的这个问题很好的解释了这个问题的应用场景。

希望将某个目录下的每个c文件编译成一一对应的执行文件,x.c 编译成 x, y.c 编译成 y。

SRCS = $(wildcard *.c)
PROGS = $(patsubst %.c,%,$(SRCS))

all: $(PROGS)

%: %.c
        $(CC) $(CFLAGS)  -o $@ $<

如果没明白发生了什么,通过下面的例子大家应该可以明白。

Makefile:

SRCS = $(wildcard a.txt)
DESTS = $(patsubst %.txt, %.json, $(SRCS))

all: $(DESTS)

%: *.txt
    @echo $@
    @echo $<

在命令行下执行

touch a.txt b.txt c.txt
make

将会输出

a.txt
a.json
b.txt
b.json
c.txt
c.json

再举一个实际应用场景的例子,希望把某个目录下的 .csv 文件编译成 .json, 这一方法不仅能简化csv to json 脚本,还可以实现类似,仅当csv文件比json文件更新的情况下才需要编译。

make, build


关于UDP的一些事

UDP协议速度更快,但不可靠,是一种无连接的协议。TCP是基于连接的协议。但是TCP并不适合不稳定的网络环境,如移动网络。 所以我们需要UDP可靠传输。

UDP可靠传输协议,有一个开源项目叫UDT,使用一种算法来达到可靠传输的目的,The UDT Congestion Control Algorithm

相关协议还有RUDP(Reliable UDP),和SRUDP(Simple Reliable UDP)。

RTP 已是视频等内容的标准。

对UDP丢包率影响最大的是数据包的大小。

以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的.这个1500字节被称为链路层的MTU(最大传输单元).但这并不是指链路层的长度被限制在1500字节,其实这个MTU指的是链路层的数据区.并不包括链路层的首部和尾部的18个字节.所以,事实上,这个1500字节就是网络层IP数据报的长度限制.因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节.而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的.又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节.这个1472字节就是我们可以使用的字节数。:)

当我们发送的UDP数据大于1472的时候会怎样呢?这也就是说IP数据报大于1500字节,大于 MTU.这个时候发送方IP层就需要分片(fragmentation).把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重组.这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,接收方便无法重组数据报.将导致丢弃整个UDP数据报。 因此,在普通的局域网环境下,我建议将UDP的数据控制在1472字节以下为好. 进行Internet编程时则不同,因为Internet上的路由器可能会将MTU设为不同的值.如果我们假定MTU为1500来发送数据的,而途经的某个网络的MTU值小于1500字节,那么系统将会使用一系列的机制来调整MTU值,使数据报能够顺利到达目的地,这样就会做许多不必要的操作.鉴于 Internet上的标准MTU值为576字节,所以我建议在进行Internet的UDP编程时.最好将UDP的数据长度控件在548字节 (576-8-20)以内.

是否需要校验?这是一个问题。理论上无论TCP 还是 UDP,都是需要校验的。

TCP链接如何保证可靠性?

TCP的数据包中记录了序号(seq)和应答号(ack)两个字段。三次握手成功后,seq被初始化。传输过程中,TCP继续使用这个序号来标记发送的每个数据包,发送端每传送一个数据包,序列号加一。接收端每接受一个数据包,会用ACK应答哪个seq标记的数据包收到了。

通过上述过程,TCP链接就可以保证通信的可靠性了。1. 针对于丢包或者延迟,TCP定义了重发机制。发送端监听接收端返回的ACK包,如果在一个时间窗口内发送端未能接收到ACK包,发送端就认为发送失败,重发该数据包。2. 数据包的重发机制就会导致包的重复,针对包的重复,TCP根据包的seq字段去重复。接收端接收到数据包之后,查看其seq字段,如果已经成功接收该数据包,则丢弃这个数据包。3. IP包的转发机制可能导致包的乱序,针对包的乱序,TCP同样根据包的seq字段重装数据段。保证了每个数据包能够以正确的顺序,无重复的传输到接收端,也就保证了TCP链接的传输可靠性。

UDP可能出现的问题

因此,UDP报文可能会出现丢失、乱序、延时等问题。

udp, network


消息服务器集群的管理

N台服务器,N > 10,相互之间会有通信,每台服务器都会开启数个进程监听数个端口用于接收来自其他服务器的消息。每个进程都必须设置一个id,其他服务器发送消息时需要根据目标服务器的id获取该id对应的进程ip和port。

静态配置

all_server_ids[id] = {host: 'xxx', port: 1234};

启动每个进程时,用参数指定id,如 ./run-server --id 123,

host, port = all_server_ids[id]

缺点:配置繁琐,服务器多的时候容易出错。

用KeyValue数据库注册,

在进程启动后, id = db.incr('server-id'); db.set('sid:'+id, 'host:port');

在发送消息时, host, port = db.get('sid' + id) 缺点:获取host,port的操作会很频繁,无法根据消息接收人id做hash来得知目标服务器id。

中央服务器

所有消息都通过一个中央服务器转发。所有节点服务器只与中央服务器通讯。所有节点服务器使用统一的配置连接中央服务器。消息发送至中央服务器。


About 3D

ray-trace 光线跟踪,镜面 radiosity 辐射光照 rasterizing 光栅化,scan line

你的引擎需要提供的包括:曲面(curved surfaces)、动态光线(dynamic lighting)、体雾(volumetric fog)、镜面(mirrors)、入口(portals)、天空体(skyboxes)、节点阴影(vertex shaders)、粒子系统(particle systems)、静态网格模型(static mesh models)、网格模型动画(animated mesh models)。

Renderer/Engine Core (渲染/引擎 内核) 哈~是呀,所有的人都热爱3D图象渲染!因为这边有着非常多的不同种类的3D世界渲染方式,可要为各类拥有不同工作方式的3D图形管道做出一个概要描述也是几乎不可能的。 不管你的渲染器如何工作,最重要的是将你的渲染器组件制作得基化(based)与干净(clean)。 首先可以确定的是你将拥有不同的模块来完成不同的任务,我将渲染器拆分为以下几个部份:可见裁减(Visibility)、碰撞检测与反馈(Collision Detection and Response)、摄像器(Camera)、静态几何体(Static Geometry)、动态几何体(Dynamic Geometry)、粒子系统(Particle Systems)、布告板(Billboarding)、网格(Meshes)、天空体(Skybox)、光线(Lighting)、雾(Fogging)、节点阴影(Vertex Shading)和输出(Output)。 其中每一个部分都得需要一个接口来方便地实现改变设置(settings)、位置(position)、方向(orientation)、以及其他可能与系统相关的属性配置。 即将显露出来的一个主要缺陷便是“特性臃肿”,这将取决于设计期间你想实现什么样的特性。但如不把新特色置入引擎的话,你就会发觉一切都将变的很困难,解决问题的方式也显得特别逊色。 还有一件有意义的事便是让所有的三角形[triangles](或是面[faces])最终在渲染管道里经过同一点。(并非每次的每个三角形,这里讨论的是三角形列表[triangle lists]、扇形[fans]、带形[strips]、等) 多花一些工作让所有物体的格式都能经过相同的光线、雾、以及阴影代码,这样就能非常便利地仅通过切换材质与纹理id就使任何多边形具有不同的渲染效果。 这不会伤及到被大量被渲染绘出的点,但是一旦你不当心,它可能会导致大量的冗余代码。 你也许最终便能发现,实现所有这些你所需的极酷效果可能只占了所有的15%左右的代码量甚至更少。这是当然的,因为大多数游戏引擎并不只是图形表现。

3D繪圖(3D Graphics Pipeline ) http://www.ategpu.com/2009/06/04/3d%E7%B9%AA%E5%9C%963d-graphics-pipeline.html

3.1 Transformation & Lighting ModelTransformation, View Transformation, 视点坐标系 HomogeneousCoordinate System , 4x4 Transformation Matrix

3.2 Viewport Transformation & Clipping & Culling Clip coordinate是將視點座標進行投影(Projection),在Eye coordinate上,我們的原點就是攝影機,視線方向是-Z軸,加上視角與遠近平面,我們創建了一個梯形體的三維空間,近平面(也就是投影平面)是梯形體較小的矩形,遠平面是梯形體較大的矩形,而所有在這個梯形體的內的Vertex,就是我們在螢幕上會看見的Vertex。因此超出這個梯形體的場景,都被視點去除(Frustum Culling)掉了。

為什麼我們在投影完之後還要留下Z座標的值呢?這是因為「Vertex離投影面的距離」可以用來處理三角面間相互遮蓋的情形,也就是哪個三角面在前,哪個三角面在後。這個稱作Z-buffer的技術會在之後提到。

3.3 Primitive Assembly & Triangle Setup 進行背面去除(Back-face Culling)。

3.4 Rasterization

3.5 Pixel Operation Texture operation 紋理操作,也就是根據Pixel的紋理座標,查詢相應的紋理(Texture),來計算Pixel該有的顏色。 . Blending 混色,根據目前已經畫好的顏色,與現在正在算的顏色的透明度(Alpha),混合兩種顏色,當作新的顏色輸出。 . Filtering 將正在算的顏色經過某種濾鏡(Filtering)後輸出。關於filtering的理論牽涉到數位訊號學,請暫時理解為,經過一種數學運算之後變成了新的顏色。


Use varnish

Varnish 是一个反向代理服务器,并且只能作为反向代理。可编程式的配置。性能很好。


如何学习线性代数

曾经看了几本线性代数的书和视频,但是越看越迷惑,大多是直接上来说定义和公式,不了解线性代数的几何意义和应用。

最终这个疑惑被一本不是专门介绍线性代数的书解决了,书名叫做《Mathematics for 3D Game Programming and Computer Graphics》,这本书很好的解释了线性代数的几何意义。


javascript 日期处理

计算两日期间的天数之差

function treatAsUTC(date) {
    var result = new Date(date);
    result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
    return result;
}

var millisecondsPerDay = 24 * 60 * 60 * 1000;
function daysBetween(startDate, endDate) {
    return Math.floor(treatAsUTC(endDate) / millisecondsPerDay) - Math.floor(treatAsUTC(startDate) / millisecondsPerDay);
}


再探魔兽世界

日常任务

货币、声望、荣誉。。。

副本、英雄副本、团队副本

社交、公会

商业技能


游戏赌博设计

暗黑创造了赌博系统。这个概念被暗黑刻意弱化了,赌博概率过低,页游将他发扬光大。 打怪物掉随机掉装备。 打怪掉装备与赌博系统有差别吗?一个投入的是时间,一个投入的是金钱。

暗黑符文系统,宝石系统,插槽系统。个性化。 英雄联盟符文系统,天赋系统。个性化。

神仙道命格系统————赌博+个性化。

抢劫系统与竞技场系统。同为PvP。

天梯、竞技场 与 抢劫是两条不同的线。

天梯是目标。天梯是单向的。 抢劫是手段。抢劫是乱斗。

活动战,仙道会,帮派战。

世界boss与副本。

game


install git-extras

git delete merged branches

if you have some branch want to ignore, please add some special file in that branch

git


redis leveldb

redis protocol + leveldb storage = perfect key/value database

NoSQL


How to enable fenced code block in github pages

Github pages最近升级了jekyll 0.12.0, 这一版本支持fenced code block.

in your _config.yml

markdown: redcarpet
```ruby
def foo
  puts 'foo'
end
```
def foo
    puts 'foo'
end
{% highlight ruby linenos=table %}
def foo
  puts 'foo'
end
{% endhighlight %}

to:

1
2
3
def foo
  puts 'foo'
end

如你所见,鄙人想增加行号,但是失败了。

非常遗憾的是,tag pages依然不被支持

github


Game server architecture

  • ✓ Router
  • ✓ SessionContext
  • ✓ AppContext
  • SuperManager - load player(from online, pool or db), create player
  • SessionManager - player online, player offline, send message to other player
  • WorldManager - A whole world controller (get player ? find player, get clans)
  • ✕ RoomManager sub world?
  • ✕ RoomNodeManager Room is tree?
  • ✓ PlayerWritePool - PlayerCache -
  • ✓ PlayerStore -

game


Unix signals

转载: http://blog.csdn.net/ljx0305/article/details/2904056

 SIGHUP    终止进程    终端线路挂断
 SIGINT    终止进程    中断进程
 SIGQUIT   建立CORE文件终止进程,并且生成core文件
 SIGILL   建立CORE文件      非法指令
 SIGTRAP  建立CORE文件      跟踪自陷
 SIGBUS   建立CORE文件      总线错误
 SIGSEGV  建立CORE文件      段非法错误
 SIGFPE   建立CORE文件      浮点异常
 SIGIOT   建立CORE文件      执行I/O自陷
 SIGKILL  终止进程    杀死进程
 SIGPIPE  终止进程    向一个没有读进程的管道写数据
 SIGALARM  终止进程    计时器到时
 SIGTERM  终止进程    软件终止信号
 SIGSTOP  停止进程    非终端来的停止信号
 SIGTSTP  停止进程    终端来的停止信号
 SIGCONT  忽略信号    继续执行一个停止的进程
 SIGURG   忽略信号    I/O紧急信号
 SIGIO    忽略信号    描述符上可以进行I/O
 SIGCHLD  忽略信号    当子进程停止或退出时通知父进程
 SIGTTOU  停止进程    后台进程写终端
 SIGTTIN  停止进程    后台进程读终端
 SIGXGPU  终止进程    CPU时限超时
 SIGXFSZ  终止进程    文件长度过长
 SIGWINCH  忽略信号    窗口大小发生变化
 SIGPROF  终止进程    统计分布图用计时器到时
 SIGUSR1  终止进程    用户定义信号1
 SIGUSR2  终止进程    用户定义信号2
 SIGVTALRM 终止进程    虚拟计时器到时

1) SIGHUP 本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控 制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端 不再关联.

2) SIGINT 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出

3) SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl-)来控制. 进程在因收到 SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信 号.

4) SIGILL 执行了非法指令. 通常是因为可执行文件本身出现错误, 或者试图执行 数据段. 堆栈溢出时也有可能产生这个信号.

5) SIGTRAP 由断点指令或其它trap指令产生. 由debugger使用.

6) SIGABRT 程序自己发现错误并调用abort时产生.

6) SIGIOT 在PDP-11上由iot指令产生, 在其它机器上和SIGABRT一样.

7) SIGBUS 非法地址, 包括内存地址对齐(alignment)出错. eg: 访问一个四个字长 的整数, 但其地址不是4的倍数.

8) SIGFPE 在发生致命的算术运算错误时发出. 不仅包括浮点运算错误, 还包括溢 出及除数为0等其它所有的算术的错误.

9) SIGKILL 用来立即结束程序的运行. 本信号不能被阻塞, 处理和忽略.

10) SIGUSR1 留给用户使用

11) SIGSEGV 试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据.

12) SIGUSR2 留给用户使用

13) SIGPIPE Broken pipe

14) SIGALRM 时钟定时信号, 计算的是实际的时间或时钟时间. alarm函数使用该 信号.

15) SIGTERM 程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和 处理. 通常用来要求程序自己正常退出. shell命令kill缺省产生这 个信号.

17) SIGCHLD 子进程结束时, 父进程会收到这个信号.

18) SIGCONT 让一个停止(stopped)的进程继续执行. 本信号不能被阻塞. 可以用 一个handler来让程序在由stopped状态变为继续执行时完成特定的 工作. 例如, 重新显示提示符

19) SIGSTOP 停止(stopped)进程的执行. 注意它和terminate以及interrupt的区别: 该进程还未结束, 只是暂停执行. 本信号不能被阻塞, 处理或忽略.

20) SIGTSTP 停止进程的运行, 但该信号可以被处理和忽略. 用户键入SUSP字符时 (通常是Ctrl-Z)发出这个信号

21) SIGTTIN 当后台作业要从用户终端读数据时, 该作业中的所有进程会收到SIGTTIN 信号. 缺省时这些进程会停止执行.

22) SIGTTOU 类似于SIGTTIN, 但在写终端(或修改终端模式)时收到.

23) SIGURG 有"紧急"数据或out-of-band数据到达socket时产生.

24) SIGXCPU 超过CPU时间资源限制. 这个限制可以由getrlimit/setrlimit来读取/ 改变

25) SIGXFSZ 超过文件大小资源限制.

26) SIGVTALRM 虚拟时钟信号. 类似于SIGALRM, 但是计算的是该进程占用的CPU时间.

27) SIGPROF 类似于SIGALRM/SIGVTALRM, 但包括该进程用的CPU时间以及系统调用的 时间.

28) SIGWINCH 窗口大小改变时发出.

29) SIGIO 文件描述符准备就绪, 可以开始进行输入/输出操作.

30) SIGPWR Power failure

有两个信号可以停止进程:SIGTERM和SIGKILL。 SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。在某些情况下,假如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。

对于SIGKILL信号,进程是不能忽略的。这是一个 “我不管您在做什么,立刻停止”的信号。假如您发送SIGKILL信号给进程,Linux就将进程停止在那里。


使用GitStats了解项目活动情况

GitStats


node.js events scope

Below code display world, it means that the scope of node.js event listener is just the event emmitter itself.

var util = require('util');
var EventEmitter = require('events').EventEmitter;

function Foo(name) {
  EventEmitter.call(this);
  this.name = name;
}

util.inherits(Foo, EventEmitter);

var foo = new Foo('world');
foo.on('hello', function(){
    console.log(this.name);
});

foo.emit('hello');


肖维勒准则

数据中并不总是合法数据,为了更好的完成统计,我们必须剔除异常的数据。

如何剔除异常的实验数据(Outlier rejection),有许多的方法。

介绍一种易于实现的方法,叫做肖维勒准则(Chauvenet's criterion)

平均值

mean = sum(v) / n

标准差

sd = sqrt(sum(v(i) * v(i) - mean * mean, i=1 to n) / (n - 1))

肖维勒准则(Chauvenet's criterion)

如果某样本数据d满足

|v(d)| > w(n) * sd

则认为v(d)是一个异常数据,将其剔除。

W(n) 是一个常数,可以用查表法获得

Table of Chauvenet’s Criterion for data rejection, with curve fit equation

Chauvenet's Criterion

--------------------------
| n          | c         |
--------------------------
| 3          | 1.38      |
| 4          | 1.54      |
| 5          | 1.65      |
| 6          | 1.73      |
| 7          | 1.8       |
| 10         | 1.96      |
| 15         | 2.13      |
| 25         | 2.33      |
| 50         | 2.57      |
| 100        | 2.81      |
--------------------------
|c = 0.9969+0.4040*ln(n) |
--------------------------

很奇怪,通过公式获得的结果和表上给的结果并不一致。

algorithm


Redis-extras and script test

redis-mock

https://github.com/guileen/redis-extras


Deploy node.js apps with supervisor

许多的文章介绍Node应用部署都是使用upstart 或是手动编写 init script, 我个人是很不习惯为每个应用去配置启动脚本。

本文所要介绍的supervisor是配置式的,配置启动命令,环境变量,进程数,等等。

进入正题:

创建用户nodeapp

sudo adduser --disabled-login --gecos 'Node App' nodeapp
cd /home/nodeapp

clone project

sudo -u nodeapp -H git clone repo
cd repo

Install dependencies modules

sudo -u nodeapp -H npm install -d

安装 supervisor

apt-get install supervisor

配置

[program:yourappname]
command=/usr/local/bin/node /home/nodeapp/yourappname/app.js
process_name=%(program_name)s%(process_num)s
numprocs=1
directory=/tmp
umask=022
priority=999
autostart=true
autorestart=true
startsecs=10
startretries=3
exitcodes=0,2
stopsignal=TERM
stopwaitsecs=10
user=nodeapp
redirect_stderr=false
stdout_logfile=/home/nodeapp/yourappname/logs/stdout.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stdout_capture_maxbytes=1MB
stderr_logfile=/home/nodeapp/yourappname/logs/stderr.log
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
stderr_capture_maxbytes=1MB
environment=NODE_ENV=production,B=2
serverurl=AUTO

启动

supervisorctl
> help
> update
> status
> restart yourappname

SA


GameObject properties adapter ———— 游戏数值开发要点

游戏数值是动态的,可叠加的,物品,天赋,被动技能,Buff,光环,都会改变一个GameObject的属性。

游戏数值开发的难点在于抽象。程序员必须将策划的语言抽象出来,否则物品、天赋、技能、Buff、等等会让你的代码千头万绪,错综复杂。

而如果能够很好的抽象出这些东西,将会一目了然,胸有成竹。

鄙人曾在一款塔防游戏中负责数值系统的开发。

数据抽象

  • 静态数据 - 设定 - Settings - S

  • 游戏对象 - 实例 - Instance - I

  • 实例的设定 - 实例的静态数据 - Instance Settings - IS

  • 实例当前的未叠加基本状态 - 实例裸体状态 - Instance Naked Data - IND

  • 状态叠加器们 - Instance Adapters - IA

配置数据

将策划语言转变为可被程序识别的数据,做到技能、物品可配置。

  • 物品 - 技能 - 天赋 - Adapters
    • [选择器] - [Selector] 定义作用对象,比如某天赋影响所有士兵,而另一技能只影响兽人士兵
    • [修改器] - [Modifier]
      • 属性
      • 操作符 + (增加x点) +% (增加x%)= (改变为x)
      • 值 x

game


安装gitlab

跟着安装文档一步步的安装,但是遇到了几个坑。

  1. 文档中给的 ruby 安装脚本有问题,要安装最新版的ruby。

  2. nginx 安装好后,要删掉site-enabled/default. 第一次可能会有 502 bad gameway,多试两次,多等一会就好。

  3. 修改 /home/git/.gitolite.rcGIT_CONFIG_KEYS, 从 '' 改为 '.*',否则无法创建新项目。

    GITCONFIGKEYS => '.*',

tools


Lua 工具集

Lua note on Mac

lua

brew install lua

luarocks - 包管理

brew install luarocks

luarocks install ...

试用失败

busted - BDD, like node mocha

https://github.com/Olivine-Labs/busted

inspect

https://github.com/kikito/inspect.lua 我用这个工具来debug

C++绑定到lua

tolua++

cocos2d-x tools 目录下有编译好的tolua++

编译(Mac OSX)

1.用brew安装lua

brew install lua

2.到官网下载tolua++

http://www.codenix.com/~tolua/

3.编译生成tolua++.a静态库

cd Downloads/tolua++-1.0.93/src/lib

gcc -c *.c -I../../include

ar rcsv libtolua++.a *.o

4.编译tolua++

cd Downloads/tolua++-1.0.93/src/bin

gcc tolua.c toluabind.c -I../../include -L../lib/ -ltolua++ -llua -o tolua++

5.done

tolua++ 1.0.93 not support Lua 5.2, use Lua 5.1

好久没有更新了

tolua

更新,但是没有尝试

luabind

swig

Swig 是为多语言准备的,编译lua有点重。

LuaJIT

学习cocos2d-x lua

先看了一本cocos2d-iphone的书。

看pkg文件来了解哪些功能可以使用,pkg文件也是了解cocos2d-x的好方法。

unpack

a,b,c = unpack({1,2,3})
local ret = self.db[cmd](self.db, arg[0], arg[1], arg[2])
local ret = self.db[cmd](self.db, unpack(arg))


网络游戏本质论

网络游戏的本质是什么?

游戏的本质?

游戏的历史比人类的历史还要久远。玩游戏并不是人类才有的行为,猫猫狗狗都喜欢玩游戏。人类的游戏花样更多, 在计算机和互联网的时代,这种变化更加复杂。

  • 游戏心理学

游戏制作不是胡乱拼凑。最后出来的东西四不像,没人玩。

  • 情景 体验无法体验的生活、世界。 神话、故事、小说、动漫、电影
  • 好奇 探险、解谜
  • 挑战 Puzzle。Boss。无尽。
  • 归属 与人一起玩,不想脱离群体
  • 战争 模拟战争。野心家、君主、策略。
  • 战斗 好战者。鼓励进攻。对战的策略感,紧张感。斗智为主。
  • 杀戮 角色扮演,ARPG,Dota
  • 收集 别人有的我也想有。
  • 炫耀 向周围的人、好友炫耀自己的战果。
  • 名望 让尽可能多的人注意到自己。
  • 休闲 打发时间。
  • 贪婪 投机取巧,用最少的成本获得大家都想要的东西。2,占小便宜
  • 恐惧 害怕失去、害怕死亡、害怕孤独
  • 赌博
  • 狂欢
  • 自信 寻找自信。
  • 色欲

    • 游戏反心理学
  • 挫败 挫败感是游戏大敌。要让人越战越勇,宁可杀红眼,不能让人一蹶不振。

  • 不公 不公平。成长类的游戏,要阶段性的公平。

  • 作弊

  • 懒惰

  • 重复 重复性的事情,令人厌倦。

    • 网络游戏的必要元素

游戏的特点

  • 真正的虚拟世界,与现实关联少
  • 发展、成长、进步
  • 变化
  • 时间越长忠诚度越高


NLTK

NLTK is a leading platform for building Python programs to work with human language data. http://nltk.org


MurmurHash 算法

发现一个不错的hash算法,可以用于我们的实际工作中,如sharding。

Hash可分为加密hash算法和非加密hash算法,Hash应用于加密、校验、查找、横向扩展等。

加密一般用MD5,SHA-1,校验一般CRC32。而服务器端的负载均衡方面,hash算法需要快速、分布均匀。

MurmurHash是一种非加密hash算法,特点是高运算性能,低碰撞率,分布均匀,由Austin Appleby创建于2008年,现已应用到Hadoop、libstdc++、nginx、libmemcached等开源系统。2011年Appleby被Google雇佣,随后Google推出其变种的CityHash算法。

参考:

  • [http://en.wikipedia.org/wiki/Listofhash_functions]
  • [http://en.wikipedia.org/wiki/MurmurHash]
  • [http://code.google.com/p/cityhash/source/browse/trunk/src/city.cc]

algorithm


配置文件格式比较

  1. java项目用的比较多的是 XML、properties,容错性很差,配置起来相当痛苦。

  2. 动态语言的项目往往用代码来配置,node用js配置,python用python配置,ruby用ruby配置。 优点是简单 缺点: a. 不能跨语言共享配置 b. 配置文件里面可以写代码,本身是有风险的 c. 运维人员必须了解相应的语言

  3. ini文件,是一个不错的选择,容错性较强。只是对于list类型的配置支持不好,比如一个cluster的所有host,port信息。

  4. YAML 比较简洁,是个不错的选择,但也有人不习惯这种极简的风格。 http://www.yaml.org/spec/1.2/spec.html#Preview

  5. JSON现在非常流行,但JSON的缺点也很明显的,如下面的语句是非法的

{key: 'value',} //注释

key 必须是 "key", value 必须是双引号,} 前多了个逗号,不支持注释。

前段时间node社区出现了一种新格式,叫做JSON5,免去了一些JSON的痛苦,https://github.com/aseemk/json5

如下面的配置是合法

{key: 'value',} //注释

可惜他出现于node社区,noder们可以使用JS代码来代替JSON5。所以JSON5可能无法在node社区有所发展,其他的语言实现它的可能性也就更低了。


《黑客与画家》读后感

《黑客与画家——硅谷创业之父Paul Graham文集》英文原名是 《Hackers and Painters —— Big ideas from the computer age》,中文版由阮一峰翻译。

许多人对“黑客与画家”这个标题感到不知所云,很难将黑客与画家放在一起进行对比。我初次见到这个标题,以为仅仅是描写编程与绘画之间的一些相通之处:思考方式或是创作过程。然而开卷之后,才发现有太多的惊喜,或是引人深思,或是感同身受。初看时觉得每章都是独立的,看完发现其实是环环相扣的。因为阅读多是在路上进行的,所以没有圈点,有必要再看一遍,找出那些绝妙的观点细细品味。

目录:

  1. 为什么书呆子不受欢迎
  2. 黑客与画家
  3. 不能说的话
  4. 良好的坏习惯
  5. 另一条路
  6. 如何创造财富
  7. 关注贫富分化
  8. 防止垃圾邮件的另一种方法
  9. 设计者的品味
  10. 编程语言解析
  11. 一百年后的编程语言
  12. 拒绝平庸
  13. 书呆子的复仇
  14. 梦寐以求的编程语言
  15. 设计与研究

第9章的几个小节标题:

  • 好设计是简单的设计
  • 好设计是永不过时的设计
  • 好设计是解决主要问题的设计
  • 好设计是启发性的设计
  • 好设计通常是有点趣味性的设计
  • 好设计是艰苦的设计
  • 好设计是看似容易的设计
  • 好设计是对称的设计
  • 好设计是模仿大自然的设计
  • 好设计是一种再设计
  • 好设计是能够复制的设计
  • 好设计常常是奇特的设计
  • 好设计是成批出现的
  • 好设计常常是大胆的设计

导读:

  • 1-4章 黑客、Nerd的内心与社会的偏见。
  • 5-7章 互联网时代的财富创造。
  • 8-9章 巧妙、简单的设计。
  • 10-15章 编程语言的设计与选择。

阅读此书时,连脚注都是不能放过的。

“画作永远没有完成的一天,你只是不再画下去了而已”。


github博客專業教程

準備知識

git, github, markdown

爲什麼要把博客host在github?

  • 彰顯碼農風采
  • 你的每篇文章擁有版本控制,每次修改都有版本記錄。
  • 文件,markdown,內容樣式分離。

Github

用過Github的人都知道,github會自動將markdown文件渲染爲html。所以許多項目直接用Readme.md 作爲文檔,簡單有效。有些高級點的github玩家則會爲項目創建一個github page, 你可以使用github page generator來生成頁面,如果你對自己的html/css非常有信心, 那麼我強烈建議你使用git-extrasgh-pages命令來創建一個乾淨的gh-pages分支, 在這個分支上你可以隨心所欲的編寫你的項目主頁。

github page generator

既然github可以host項目主頁,那麼他是否可以host用戶主頁呢?當然可以,否則,本文就無從談起了。方法很簡單,你只需要創建一個 USERNAME.github.com 的項目即可host你的個人主頁。文中所有USERNAME都表示你的github用戶名。

但是如果只是一堆的html/js/css堆砌而成的個人主頁,是完全無法與博客相提並論的。本文既然叫做《github博客專業教程》,自然不能只教大家host一堆靜態文件。

Step 1. 創建repository

假定你已經有了github帳號,我的github用户名是guileen,請將本文中的guileen一律替換爲你的github用戶名。

在github上創建一個新的Repository,命名爲 guileen.github.com,恭喜你,你已經有了一個屬於自己的博客空間,而且你可以隨心所欲的定製它。

接下來,把這個庫clone到本地。

git clone git@github.com:guileen/guileen.github.com.git

Step 2. index.html

在项目根目录下创建 index.html

<html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h1>Hello world</h1>
    </body>
</html>

将这个文件添加到git中

git add index.html git commit -m 'first commit' git push origin master

当你将这个文件push到github之后,访问 http://guileen.github.com ,就可以看到你的主页了。 就像你所看到的,github会自动host这个库下的静态文件,也包括 js/css/images。不过有部分文件不在次列,稍候介绍。

Step 3. 安装jekyll

大家可能会以为,github page只能host静态文件,无法完成类似,分类,分页,日期等功能。对于这些需求,github用一种很巧妙的方法来实现了。

Github初期是使用ruby开发的,现在ruby依然是github主要使用的编程语言。在ruby这样一个富有创造力的社区,诞生过很多神奇的开源项目。 而github就是使用了一个叫做jekyll的ruby项目。

Mac

gem update --system
gem install jekyll
jekyll --server --auto

Step 4. _config.yml

# Configure of jekyll

# github default configurations
safe: true
lsi: false
pygments: true

# override jekyll configurations

# use redcarpet more like github
markdown: redcarpet

# My configurations
title: 桂糊涂的流水账
ga: UA-00000000-0 

Step 4. _post

Step 5. layout

Step 6. google analytics

Step 7. comment

使用 Disqus 服务

Step 8. highlight

Step 9. share

Step 10. RSS

atom.xml

Step 11. github info

參考

  • http://jekyllrb.com/
  • https://github.com/mojombo/jekyll
  • https://help.github.com/categories/20/articles
  • http://erjjones.github.com/blog/How-I-built-my-blog-in-one-day/

github


About


Recent


Tags