玩手机是一种寂寞,珍爱生命,远离手机

catge Post in Design
7

Mobile phones and the Japanese

“侧方位停车”最后一圈半总被我打反方向,师傅训斥我“练车不专心,别人开的时候就在旁边好好学,不要只顾玩手机!”。

这句话让我为之一怔。当玩手机变成一种习惯,而我自己又不曾发觉的时候,这是多么可怕的一件事情。

记得上周末和@dfdou等一行六人去川味观吃饭,沿着桌子做好后,我们不约而同拿起各自的手机check in起来,街旁、大众点评、foursquare。讨论了一下服务员MM胸很大以后,就各自玩起手机。当时我微微一笑,“还好我也有手机玩”。

这是一个很有趣的现象。当我在前公司的时候,每周五下午会有一次团队的例会。周会上10多人,其中1/4的人会玩BMP,2/4的人会玩手机,于是老板一次次“规定”不许带电脑,不许玩手机。(可是guiding只是乌龟的屁股)

仔细想想你会发现,通常玩手机的时候会是吃饭前等菜、会议中、坐车等,分析下动机无非是:我觉得无聊,如果不玩手机就会浪费时间

@hhshushu 在上海上班,通常一个月能出差来次杭州,当我们一起吃饭的时候,不会玩手机,因为我们有太多需要交流的内容。dc 在的时候,给我们做过很多次前端技术分享,我脑海中始终还记得他那简单而又优雅的PPT风格,这种风格,我只在上届D2上@kejunz的分享上看到过。听他们的分享,我不会玩手机。当然后来做的很多次有关static和arale的分享(或者说应该是规定),我能玩手机就尽量玩。

前不久我看到陈果老师在优酷上的一节课程视频,她谈到孤独与寂寞的区别─“孤独是自成世界的独处,寂寞是迫于无奈的虚无”。正如阿桑在《叶子》中唱到“孤单是一个人的狂欢、狂欢是一群人的孤单”。据此推测,那些手机控恐怕就是寂寞党吧。

之前有位友人告诉我,她决定停止使用手机,原因是觉得“《手机》会带来太多的欺骗和不安…它带来的价值远大于它的负面影响”。一开始,我极力反对她的观点,大肆描述出游时手机上的google map和大众点评给我带来的好处。然而最后还是不得不同意:原本以为通过手机可以增强人际关系,却发现有了手机后与人交流反而更少。手机给人带来的错觉是:以为有一个号码在手,好像我就和这个人一直在保持联系着。然而,想想有多少号码,自己未曾拨打过,其中是否包括自己的亲人?

这是一种不安的现实。正如互联网的出现给知识带来的冲击如出一辙。以为有了google,自己就NB了,却不知骨子里依然是个SB。

昨天我学dc在自己的hosts上加上了一行:

0.0.0.0 t.qq.com t.sina.com.cn twitter.com renren.com

因为我花了一天时间refresh这些站点,这是一种温水煮青蛙的阴谋。坐在电脑前“不停地忙碌”就好像自己真的在忙碌,没有在浪费时间。然而,看似“狂欢”实则“孤单”。玩手机又何尝不是如此?

最后点这个链接看看伦敦的人在车上玩什么:)

http://www.flickr.com/photos/cocoarmani/2120868475/

Velocity模板开发常见问题分享

catge Post in Design,Tags:
2

velocity主题T恤

在twitter上看到 @Fenng 提到“国内分享velocity的不多”,忽然想起自己在支付宝用velocity开发了两年,和服务端开发同学也常为这个模板层的归属问题纠结不休。这也是我在淘宝上买这件velocity主题T恤的原因,上次去红京鱼吃饭,工友们对它表示了很大的兴趣^_^

直入话题,把自己这两年的velocity开发经验的精华部分分享出来吧,相信足以应对前端模板开发的日常工作。这里我准备了一个VM版的,有运行环境的同学可以放上去跑起来看看。

问:遇到vm模板开发的问题一般怎么解决?

首先官方手册PDF还是要收藏一份,英文的看不了,就去google上搜份中文手册看。手册上没有提及的只有去google.com(google.cn基本搜不到)上搜索了,用上一些英文关键字一般可以找到,实在找不到只有问周围的专业人士了。

问:如何通过URL传递整型变量到VM里?

这个问题是我在做项目的时候遇到的一个实际问题,传一个参数进来,然后运算下。当时在国外一篇很老的归档帖子中看到了解决方案。set一个新整型,然后调用它的parseInt方法把string转成int,再进行计算,代码如下:
#set($n = $!request.getParameter('n'))
#set($intNum = 0)
#set($m = $intNum.parseInt($n) + 1)

问:#parse和$tile.setTemplate()(或$control.setTemplate())区别是啥?

  • #parse是先插入后解析,$tile是先解析后插入。
  • #parse和被#parse的页面变量相互共享,$tile变量需要传入。
  • #parse是代码块无须controller,$tile是通用组件需要controller。
  • #parse需要配置系统的默认path,推荐能用#parse就不要用$tile

问:VM模板里能取到哪些业务的值?

VM是模板解析层,一般可以通过$request取到很多业务数据。比如从当前request对象中取cookie:

#foreach($cookie in $request.getCookies())
$cookie.name : $cookie.value
#end

问:${catge}、$!catge、$catge这些写法有啥区别?

这三种写法语义上是等价的。${catge}比$catge的好处是,可以用{}符号隔开变量和其他文字。$catge和$!catge区别在于当页面中不存在$catge时,$!catge将会不会再页面中显示。

问:VM里的循环、取对象什么的咋搞?

循环啥的,学会怎么用#foreach语句就好了,想知道更多去Google下velocity的参考文档。循环能做的事情很多,比如上面的遍历出request里的cookie。

这里举个绑定一系列元素的JS表单校验的例子:

"attach3": {
desc: "附件3",
depends : true,
required: true
},
"attach4": {
desc: "附件4",
depends : true,
required: true
},
"attach5": {
desc: "附件5",
depends : true,
required: true
},

千万别copy大段相通的VM代码,用这句:

#foreach ( $count in [3..5] )
"attach${count}": {
desc: "附件${count}",
depends : true,
required: true
},
#end

如果attch5是最后一个绑定元素呢?那最后一个逗号“,”就不要打出来,这里就引申出一个问题:怎样判断是否为循环的最后一次?

这里要用到一个叫$velocityCount的变量,任何循环语句中都默认有这么一个标识当前循环次数的变量,而数组的长度都可以通过size()方法获取到。

源码:

#set($array = [3,4,5])
#foreach ( $count in $array )
"attach${count}": {

desc: "附件${count}",
depends : true,
required: true
}#if($velocityCount !=$array.size()),
#end
#end

问:听说VM里有宏定义,这个啥东东?

宏定义#macro就是把一些操作封装成类似function的方式来统一处理同类问题,具体你自己去google吧。有兴趣的话建议搜索系统当中叫macros-default.vm(或macros.vm)的文件,一般的宏定义都会写在这个文件里。
需要说明的是,宏定义一般是放在某car的根目录上,在页面上也可以直接定义。宏定义修改之后需要deploy当前系统,否则方法会被缓存,看不到改动后的效果。

问:VM里怎样生成随机数

VM强大之处其实在于它的工具类,例如一般的VM都默认有$stringUtil这个字符串比较的类。
有时我们需要给URL后加个随机数清清缓存。在webx系统你可以用$randomUtils.nextDouble(),在sofa MVC试试$math.getRandom(),如果不起作用,检查下是否配置了相应的工具类。

问:如何通过VM来获取当前页面URL?

貌似前面已经提到VM可以随意调用$request对象里的方法,获取到需要的值。

//webx下获取当前页:
$rundata.getRequest().getServerName()$rundata.getRequest().getServletPath()
//sofa MVC下获取当前页:
#set($pageAbsUrl = "$!request.getServerName()"+"$!request.getContextPath()"+"$!request.getServletPath()")
//获取引用页:
$rundata.getRequest().getHeader("referer")

问:VM该前端开发来做还是服务端开发来做?有啥意义?

@catge认为服务端提供数据、接口,前端进行VM、CSS、JS开发。因为VM是DOM结构层,样式和脚本都要基于结构开发。
比如有一个需求是为某些浏览器的用户增加一个全站的XBOX弹窗,提醒用户升级到股沟浏览器。你有两种选择方案,一种是用JS判断UA信息为该浏览器,然后将已经生成好的XBOX的DOM弹出来。第二种方案是在VM里取request里的http头信息里的UA信息,判断符合条件则生成这段DOM。
咋一看,这两种方法差不多,而且通过VM来实现更复杂,因为VM里取浏览器类型和版本号十分困难,$stringUtil折腾来折腾去都没有JS来得快。
但是如果需求方说的浏览器是指IE6.0以下版本的浏览器呢?为了几千个用户给几亿用户的前端代码里加上这段JS判断?那只能说你很2。
@catge认为VM层的模板优化至关重要,VM不应该只包含业务逻辑,同时应该使用大量的展现逻辑,针对不同用户、不同来源、不同浏览器展现最优体验。

Python写的计算24点小游戏

catge Post in Design,Tags:
0

最近在学习PHP & Python,@hongqn 在他的《Python 于Web 2.0网站的应用》中提到了Python的哲学,我想这个应该就是我一直在寻找的吧。于是花了一下午在优酷上看完了《Python.Django视频教程-台湾辅仁大》的视频教程专辑,开始了写个Python小游戏的计划。

系统是Mac OS X Snow Leopard,结果装了个Xcode 3.1,啥东东都编译不了,很多python setup.py install都安装不通过。后来才知道雪豹必须装Xcode3.2+才行。

以下是我边写边学的python计算24点小游戏。求解24点算法那块我实在是没啥头绪,就这么悲剧的放着吧,毕竟这块不是我写这个小游戏的初衷。网上查了一些算法,不是错的就是用啥穷举的方法。通过写这个小游戏,我学会了以下一些内容:

1、dictionary的操作,’i’ in dict返回True or False

2、list的操作,list.append()、”.join(list)、list.sort()

3、整型随机数生成,random.randint()

4、正则表达式,re.match()、

5、字符操作,替换 string.replace()、大小转换string.upper()

6、eval()语句的用法及其安全性问题

7、类型转换,int(str)、str(int)

8、程序执行时传入自定义参数的方法,for argv in sys.argv

9、判断当前运行程序是否为其本身 __name__==’__main__’

10、指定程序字符编码encoding: utf-8 放在第一行注释中

除以上几点外,程序中用到的其他语句有:import、循环、字符串拼接、print多行。

代码展示:

# Code by yekai.net, encoding: utf-8
import random
import re
import sys

nums = []
poker = False

def conver2Cards(nums):
    cards = []
    cardDict = {'1':'A','11':'J','12':'Q','13':'K'}
    for i in nums:
        if poker and str(i) in cardDict:
            cards.append(cardDict[str(i)])
        else:
            cards.append(str(i))
    return cards

def getCards():
    newnums = []
    global nums
    for i in range(4):
        newnums.append(random.randint(1,13))
    nums = newnums;
    return conver2Cards(newnums)

def getAnswer(nums):   
    for i in nums:
        return ''.join(str(nums)) + '\n抱歉,24点算法我写不出来,请指教:http://yekai.net/?p=217'
           
def calc(exp):
    match = re.match('^\(?[0-9]{1,2}[-+*/]{1}\(?[0-9]{1,2}\)?[-+*/]{1}\(?[0-9]{1,2}\)?[-+*/]{1}[0-9]{1,2}\)?$',exp)
    if match:
        inputnums = re.split('[-+*/()]+',exp.replace('(','').replace(')',''))
        inputnums = [int(i) for i in inputnums]
        inputnums.sort()
        if nums != inputnums: return -1
        if eval(exp) == 24:
            return 1
        else:
            return 0
    else:
        return -2
   
def newGame():
    running = True
    print '-------------------\nCards:  ' +'  '.join(getCards()) + '\n'
    nums.sort()
    while True:
        x = raw_input('Input Your Answer:').upper()
        if x == 'Q':
            running = False
            print 'Game Over, bye~\n'
            break
        elif x == 'K':
            print('Answer:' + getAnswer(nums))
            break
        elif x == '':
            continue
        else:
            x = x.replace('A','1').replace('J','11').replace('Q','12').replace('K','13')
            y = calc(x)
            if(y == -2):
                print 'Please Input Correct Format,el: (2+6)*(5-2)'
            elif(y == -1):
                print 'Please use the given cards!'
            elif(y == 0):
                print 'ERROR:'+ x +'='+ str(eval(x)) + '\nPlease Try Again:)'
            else:
                print 'CORRECT!'
                break
           
    if running:
        newGame()
    else:
        sys.exit()

if __name__=='__main__':
    for argv in sys.argv:
        if(argv == 'poker=on'):poker = True
    print """
======Welcome to calc24 game======
Notes:
[Q] Exit Game
[K] Get Answer
Poker Mode: poker=on
"""

    newGame()

下载源文件:calc24.py