回首2009,展望2010

2009年底,空间商抱着机器从上海跑到重庆再跑到北京,也没让我赶在年末写上一份总结。也能理解,都不容易,现在正常了,也顺道展望一下2010。

回首2009,是有些收获:
1,学习了python。虽然是刚刚入门,总算是写了一个在线聊天的服务器。php虽然好使,但语言特性还是很难遇上诸如内存释放,线程,管道之类的问题,不遇到问题就没有机会搞懂。
2,封装了一个PHP框架。虽然我很鄙视我在做重复的工作,但是thinkphp,zf真的让我感觉很不方便。我有自已习惯,也知道程序部署的环境,所以就很简单,借鉴了部门老大对zf的修改,使用autoload自动加载,用xdebug测试的时候,基本上效率没有什么影响。
3,从09年4月份开始,中间虽然有断层,但基本上我全部精力都放在一个网页游戏上,遇到了很多问题,有的解决有的绕过。一个深刻的教训是,我以后绝不对没有做过的东西说“好做”。为了给用户更自然的体现,应用只用了一个html页面,前端js写了有5000多行,比5w行php都难写。更别提遇到的一些js内存泄漏,莫名其妙的卡,浏览器关闭。在firefox下还好,总有工具可以用。ie下那些debug工具都是不靠谱的,我只能一行一行的删除,alert调试。总算在年终的时候内测,虽然还有很多问题。

展望2010:
1,我知道js做ria的不足,所以今年的一个重要的任务就是学习flex。
2,有武侠情结,想写一个武侠类的网页游戏。因为对实时要求比较高,架构采用我熟悉的js和我不熟悉的python。一直在关注一个框架eurasia,准备尝试一下,主要还是想深入一下python,手熟一下python。
3,存xx的钱,08年09年我原地踏步走,积累了两年应该再上个台阶了。

还有一些我不想说出来的计划,我在心中也默默的说一遍。事情总有反复,事情总有后退,事情总有一日不如一日,事情总在一个漫长的周期上一直向上。
2009是很好的一年,希望2010也是很好的一年。

今天跑完一个环线

一直绕操场跑圈圈,今天和志远跑了一次环线。遥想07年初我和鸭子也是跑这条线,一直跑到我吐,那滋味真不好受。今天速度控制的还可以,跑的比较轻松。

run

QQ群前端使用的 javascript loader

开始主要想看一下qq群所使用的javascript模板,后来发现他们用的也是一个jquery的插件。
不过这个加载写的也很不错,分析了一下,原JS: http://qun.qq.com/god/m/js/loader.zh-cn.js

; (function() {
    var window = this,
    undefined,
    jLoader = window.jLoader = window.jL = {
        _version: "1.2.1",
        _sequence: [],
        _queue: {},
        _xhr: function() {
            return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
        },
        // 直接加载脚本
        _script: function(uri, context) {
            context = context || document;
            var head = context.getElementsByTagName("head")[0] || context.documentElement,
            script = context.createElement("script");
            script.type = "text/javascript";
            script.src = uri;
            head.appendChild(script);
            return script;
        },
        _style: function(uri, context) {
            context = context || document;
            var head = context.getElementsByTagName("head")[0] || context.documentElement,
            link = context.createElement("link"),
            links = context.getElementsByTagName("link", context);
            link.type = "text/css";
            link.rel = "stylesheet";
            link.href = uri;
            if (0 < links.length) {
                 var _last = links[links.length - 1];
                 _last.parentNode.insertBefore(_link, _last.nextSibling);
             } else {
                 head.appendChild(link);
             }
             return link;
         },
         _replace: function(pattern, uri, context) {
             if (!pattern || !uri) {
                 return;
             }
             context = context || document;
             var links = context.getElementsByTagName("link", context);
             for (var i = links.length - 1; i >= 0; i--) {
                if ( - 1 != links[i].href.indexOf(pattern)) {
                    links[i].parentNode.removeChild(links[i]);
                }
            }
            if (uri) {
                jLoader._style(uri, context);
            }
        },
        // 将脚本内容插入当前页面来执行
        _globalEval: function(data, context) {
            if (data && /\S/.test(data)) {
                context = context || document;
                var head = context.getElementsByTagName("head")[0] || context.documentElement,
                script = context.createElement("script");
                script.type = "text/javascript";
                if (jLoader._excute) {
                    script.appendChild(context.createTextNode(data));
                } else {
                    script.text = data;
                }
                head.insertBefore(script, head.firstChild);
                head.removeChild(script);
                return true;
            }
            return false;
        },
        // 执行回调方法数组。有可能请求多次,绑定了多个的回调方法。
        _call: function(mark) {
            if (jLoader._queue[mark].callbacks) {
                var cl = jLoader._queue[mark].callbacks.length;
                for (var j = 0; j < cl; j++) {
                    jLoader._queue[mark].callbacks[j][0](jLoader._queue[mark].callbacks[j][1]);
                }
            }
        },
        // 这是一个顺序加载的过程,每加载一个JS,都会放入sequence队列,如果depend=true,则该脚本之前的脚本全部加载完后该脚本才执行
        _inject: function() {
            var len = jLoader._sequence.length;
            for (var i = 0; i < len; i++) {
                var seq = jLoader._queue[jLoader._sequence[i]];
                if (!seq.done) {
                    if (!seq.response) {
                        return;
                    } else {
                        seq.done = true;
                        seq.response = [seq.response, ";jLoader._call(\"", jLoader._sequence[i], "\");"].join("");
                        jLoader._globalEval(seq.response);
                    }
                }
            }
        },
        scripted: function(mark) {
            if ("undefined" == typeof jLoader._queue[mark]) {
                return false;
            } else {
                if (jLoader._queue[mark].done) {
                    return true;
                } else {
                    return false;
                }
            }
        },
        script: function(options) {
            options = options || {};
            // 参数不全
            if (!options.mark || !options.uri)
            return;
            options.depend = options.depend || false;
            options.params = options.params || {};
            options.onload = options.onload || null;
            // 如果没有依赖关系和回调方法,则直接引入
            if (!options.onload && !options.depend) {
                jLoader._script(options.uri);
                jLoader._queue[options.mark] = {
                    uri: options.uri,
                    response: null,
                    done: true
                };
                return;
            }
            // 是否为第一次请求
            if ("undefined" == typeof jLoader._queue[options.mark]) {
                jLoader._queue[options.mark] = {
                    uri: options.uri,
                    response: null,
                    done: false
                };
                // 设置回调方法和回调的参数
                if ("function" == typeof options.onload) {
                    jLoader._queue[options.mark].callbacks = [[options.onload, options.params]];
                }
            } else {
                // 虽然不是第一次请求,但有没有真正加载。没有真正加载的原因此时正在异步请求脚本内容
                if (false == jLoader._queue[options.mark].done) {
                    // 如果已经设置为callbacks, 则追加callbacks, 前面设置的callbacks是数组
                    if ("function" == typeof options.onload) {
                        if ("undefined" == typeof jLoader._queue[options.mark].callbacks) {
                            jLoader._queue[options.mark].callbacks = [[options.onload, options.params]];
                        } else {
                            var cl = jLoader._queue[options.mark].callbacks.length;
                            jLoader._queue[options.mark].callbacks[cl] = [options.onload, options.params];
                        }
                    }
                } else {
                    // 已真正加载,直接执行回调方法
                    if ("function" == typeof options.onload) {
                        options.onload(options.params);
                    }
                }
                return;
            }
            // 将脚本按顺序放入队列,self._inject会用到
            var len = jLoader._sequence.length;
            if (options.depend) {
                jLoader._sequence[len] = options.mark;
            }
            var xhr = jLoader._xhr();
            xhr.onreadystatechange = function() {
                if (4 == xhr.readyState) {
                    // 如果设置了依赖关系,则检查依赖。如果没有设置,则执行脚本内容和回调函数
                    if (options.depend) {
                        jLoader._queue[options.mark].response = xhr.responseText;
                        jLoader._inject();
                    } else {
                        jLoader._queue[options.mark].done = true;
                        var response = [xhr.responseText, ";jLoader._call(\"", options.mark, "\");"].join("");
                        jLoader._globalEval(response);
                    }
                }
            };
            xhr.open("GET", options.uri, true);
            xhr.send("");
        }
    };
    // 很好,很强大,因为getTime()结果不一样,所以用这种方法可以准确的定位到某一个类有没有执行
    jLoader._excute = false;
    var root = document.documentElement,
    script = document.createElement("script"),
    id = "script" + (new Date).getTime();
    script.type = "text/javascript";
    try {
        script.appendChild(document.createTextNode("window." + id + "=1;"));
    } catch(e) {}
    root.insertBefore(script, root.firstChild);
    if (window[id]) {
        jLoader._excute = true;
        delete window[id];
    }
    root.removeChild(script);
})();

看完《蚁族》

在唐家岭住了2年多,终于看到一本描述唐家岭的书《蚁族》,立马和同在这儿住的同事买了,看完后发现虽然不是很全面但还是真实客观的。只是那些调查人员感觉唐家岭脏,乱在我眼里却很平常,或许我习惯了,除了下雨天路难走,别的还可以。

在唐家岭住,生活成本比较低,吃饭的地方比较多,而且租一间房子比合租小区更自由。除了难挤的公交车,我觉得这里倒是暂住的好地方。另外,这本书后面个别章节有一种在上俯视众生,我很不喜欢。唐家岭虽然没那么好,但也没那么惨,在这里住两年就知道了。

20091112112       20091112112

还是值一买本,当当链接:http://product.dangdang.com/product.aspx?product_id=20684969
前三章节试读:http://book.ifeng.com/book.php?book_id=2414

update 100210:做为一个在唐家岭的蚁族,我认为张鸣的这篇文章远比廉思的那本书要清醒和现实 http://news.qq.com/a/20100210/001085.htm

使用自己的FTP做为xmark的服务器

在众多网站阵亡之后,我最常用,最必不可少的xmark也倒下了。
因为平时在公司和在家里用的不是一台电脑,很多收藏要同步,每次同步都要挂代理,太麻烦了。在xmark里有选项可以使用自己的服务器,试了一下,只要是简单的FTP权限即可以,而且速度比以前也理想。
1。在 【设置】- 【status】里面填上自己的FTP用户名和密码
status

2。在 【设置】 – 【高级】中, 填上在FTP的保存收藏的URI,xmark会在服务器自动建立文件。
2

国内虚拟主机架设dabr

基于dabr212修改的,下载附件,然后覆盖 common 目录下的 twitter.php 文件,请求API的速度大概在1秒左右比较慢,最好是自己用。

下载文件

update 20091030:国内的虚拟主机可以架设一个,将文件覆盖即可,方便手机访问。主要是将dabr原来curl请求 twitter api的方式,换成一个socket方试请求,使用一个twitter上推荐的,号称不会被封的ip,并且使用了https,测试功能一切正常。

hello world

sablog的代码高亮不怎么方便,换成新版的wp,感觉还不错。
旧BLOG:http://yuehei.37net.com/old/
更旧BLOG:http://hi.baidu.com/wooo

_role);
		$ret = $modelExp->listExp();
		if ($ret === false) {
			exit(json_encode(array('status' => 0)));
		} else {
			$timestamp = time();
			$sec = strtotime($ret['end_time']) - $timestamp;
			exit(json_encode(array('status' => 1, 'sec' => $sec, 'map_id' => $ret['map_id'])));
		}
	}
}
#!/usr/bin/python#Filename:socket_server.py
# coding=utf-8
# 聊天网关

from twisted.internet import protocol, reactor
import time, os, qing_game

PORT = 8888