星期三, 8月 25, 2010

一定要自己踢過一次鐵板才能學會 (二)

經過一夜的蒐集資料, 看了Google I/O的影片, 覺得用MapReduce就是正解啦.

用法很簡單
Step 1
Download最新的MapReduce, 在local自己的appengine程式的地方執行.

svn checkout http://appengine-mapreduce.googlecode.com/svn/trunk/python/src/mapreduce
Step 2
修改app.yaml, 固定都是加上下列這段code.

- url: /mapreduce(/.*)?
  script: mapreduce/main.py
  login: admin
Step 3
新增一個mapreduce.yaml檔

mapreduce:
- name: Count the number of entities
  mapper:
    input_reader: mapreduce.input_readers.DatastoreInputReader
    handler: jobs.process
    params:
    - name: entity_kind
      default: main.Report
  • 第一個name, 就是之後會顯示在mapreduce的網頁介面上的job name.
  • input_reader, 目前有四種reader可以選, 詳情可見這裡. 主要是從DataStore裡抓, 或是從BlobStore裡抓, 或是從zip檔裡抓資料.
  • handler, 指定之後會被MapReduce call的function. 這裡有點tricky, 文件寫得不是很清楚, 查了MapReduce的source才知道要填什麼. 簡單的說它可以吃三四種格式, 會試著用不同的方法去找到對應的python檔, class定義跟function定義. 最簡單的方法就是"file.function". 像這裡就是有一個叫jobs.py的檔, 裡面有一個process(). 之後MapReduce就會一直重覆地呼叫這個function.
  • param, 這裡可以指定一些參數, 最重要的是entity_kind這個欄位, 這裡指定了預設值是main.py裡定義的Report model. 之後MapReduce每次call jobs.py裡的process function時, 給他的參數就是Report model裡的其中一個entity. 如此不斷重覆, 直到把Report model裡的所有entity都走過一遍.
Step 4
寫一個job.py

from mapreduce import operation as op
from main import Report

def process(report):
  yield op.counters.Increment("total")

Step 5
上傳到appengine後, 在網頁上看MapReduce的操作介面. 連到自己的網址http://xxxx.appspot.com/mapreduce, 長相會這樣.


在Launch jobs那裡, 會看到剛才在mapreduce.yaml裡指定的mapper名. 下面entity_kind可以看到我們設的預設值, main.Report. 接下Run就會開始執行.

Step 6

這就是結果了, 在右上角可以看到Counter的值是882. 代表Report model總共有882個entities. 用這個方法, 我就可以做其它更細部的統計了.

星期二, 8月 24, 2010

一定要自己踢過一次鐵板才能學會 (一)

在公司的一個appengine程式, 終於蒐集了一小筆資料(不到一千筆), 現在想對這些資料做些統計, 再用Google Chart API顯示出來. 可以預期等到這個程式正式上線, 資料是幾十幾百萬來計算的時候, 這個統計方法一定會有問題, 不過我還沒什麼想法, 現在一開始是這麼做的.


星期一, 8月 23, 2010

interview

最近畢業季, 一口氣interview了不少台大, 交大, 台科大畢業的新鮮人. 雖然有些不是根正苗紅的資訊相關科系畢業, 但是平均來說水準堪憂.

我已經搞不懂現在的資訊系在教什麼了, 最基本資料結構, 演算法都沒什麼概念. 寫個sort也寫得零 零落落. 別人可以說我不用會那麼多, 只要會用library就可以了. 但是身為相關科系的畢業生也不知道裡面的原理跟門道就說不過去了.

程式語言也是, 現在很多學生可能在大學的六年就只接觸Java. 其實會Java很好, 但是不夠底層, 它把太多 CPU特性包裝起來, 寫程式的時候接觸不到. 習慣後以為這就是電腦科學的全部, 無法寫系統程式. 如果C也不會, 那其它像是Lisp, Scheme, Prolog這些語言應該更是沒有概念.

會不會寫這些語言不是重點, 而是這些語言背後代表的想法. 如果從來沒有接觸過, 就會缺少一種把問題抽象化的可能想法. 那麼在解決問題的時候就可能是用硬幹的, 而不是一個優雅的解法.

面試這些人的感覺是, 大家的興趣都很廣, 通識修了不少, 自己本科的東西修的不多. 我考的題目他們在考研究所的時候一定都會, 但是當場就是寫不出來, 代表這些東西曾經是用背的, 而不是理解後又常常用到. 所以我猜本科的的課程的作業或是Project又不是太難, 所以底子不深.

再面試一輪就要做決定了, 再看看有沒有讓人驚艷的吧...

星期五, 8月 20, 2010

CSS之二

  • 很多屬性都有分top, bottom, left, right. 通常可以合在一行寫, 有四種組合.
    1. padding: 25px 50px 75px 100px (上25, 右50, 下75, 左100)
    2. padding: 25px 50px 75px (上25, 左右50, 下75)
    3. padding: 25px 50px (上下25, 左右50)
    4. padding: 25px (上下左右都25)
  • Grouping
    • 可以用逗號隔開幾個selectors, 這幾個的效果是一樣的.
      h1,h2,p {
      color: green;
      }
  • Nesting
    p {
    color: blue;
    text-align:center;
    }
    .marked {
    background-color: blue;
    }
    .marked p {
    color: white;
    }
  • 要把某個東西隱藏起來. 用display: none; 或是visibility: hidden; 但是這兩個有點不同.
    • display: none; (東西消失, 後面的東西擠過來)
    • visibility: hidden; (東西消失, 但是還是會佔據一塊同樣大小的位置, 後面的東西不會擠過來)
  • block element
    • 像是<h1>, <p>, <div>這種, 它會把所有可用的寬度都佔掉. 而且在前後都換一行.
  • inline element
    • 像是<span>, <a>這些, 它只會用掉它自己需要的寬度.
  • 以上這兩種屬性, 可以用display來改掉.
    li {
    display: inline;
    }

星期四, 8月 19, 2010

CSS之三 Positioning

這個是我比較有興趣的地方.

  • 有四種定位的方法
    1. Static Positioning
      • 預設的方法
      • 不受top, bottom, left, right影響
    2. Fixed Positioning (position: fixed;)
      • 指定東西出現在某個相對於browser window的位置
      • 即使window在捲動時, 它還留在原位, 不會跟著捲
      • example
      • 它接下來的element會當它不存在一樣, 繼續往下排
    3. Relative Positioning (position: relative;)
      • 相對於它原本應該出現的位置, 另外加上一個offset
      • ex. (left: -20px;)
      • 雖然用了relative positioning的element的顯示位置會變, 但是接下來的element, 還是會用它用本應該存在的座標, 繼續畫下去
    4. Absolute Positioning (position: absolute;)
      • 相對於他的parent的位置.
      • 如果沒有parent, 那就是<html>
      • 它接下來的element會當它不存在一樣, 繼續往下排
  • z-index, 大的排前面, 小的排後面. 可以是負的.
  • cursor, 有一大堆屬性, 可以改變cursor的外觀
  • overflow: scroll; 可以讓內容超出範圍時, 加上一個scroll bar

星期二, 8月 17, 2010

買GMail空間了...

GMail終於要爆了, 剩下不到50MB囉.


於是乎決定花個一年五塊美金加大空間. 買了之後變這樣.


剩20G了

要注意喔, 買這個需要一個工作天的時間才生效, 不能等到信箱真的爆了才申請, 否則就會有一段時間收不到信了...

CSS之一

現在在施行混亂學習大法, 寫到哪裡卡到哪裡, 卡到哪裡學到哪裡. 今天是卡在CSS上. 有個簡單排版的效果我做不出來, 查了好一陣子. 最後還是在PTT上問到答案... 在這裡記錄一下CSS我在W3CSchool做了啥.

  • CSS是Cascading Style Sheet的縮寫 (話說cascading出現在我的碩士論文裡很多次)
  • HTML本來不是設計來做排版的, 而是設計來描述一篇文章的結構. 例如head, title, paragraph等等. 用font, color來做一些效果, 一直都是問題.
  • 在HTML 4之後, 號稱可以把這些描述怎麼畫內容的方法, 都獨立於HTML之外, 寫在css檔裡.
  • selector 跟 declarations
  • selector有幾種方法, 最簡單的就是統html的tag, 像是p, h1等等.
    p {
    color: red;
    text-align: center;
    }
  • css裡的註解寫法跟C的一樣, 用/* */包起來.
  • 也可以設id的style, id就是某個element的特定的名字, 應該只能有一個. 要用#來指定.
    #para1 {
    color: red;
    text-align: center;
    }
  • id不可以是數字開頭的!
  • class是第三種, 跟id不同的是, 它是描述一"類", 而不只是特定一個tag. 它是用.來指定.
    .center {
    text-align: center;
    }
  • class也可以特別指定要在哪一種tag上生效. 例如下面, 就只有<p class="center"></p>的會生效.
    p.center {
    text-align: center;
    }
  • 加入CSS也有三種方法, external, internal, inline.
  • external就是在HTML一開始include一個css檔進來.
    <head>
    <link rel="stylesheet" type="text/css" href="xxx.css" />
    </head>
  • internal則是在HTML一開始的header裡寫一些css script.
    <head><br /><style type="text/css"><br />hr {color:sienna;}<br />p {margin-left:20px;}<br />body {background-image:url{"images/back40.gif"};}<br /></style><br /></head> 
  • inline就在該tag裡直接加了.
    <p style="color:sienna;margin-left:20px">This is a paragraph.</p>
  • 如果一個tag的style同時被不同的selector指定時,  所有的attribute都會被設下去. 如果有重覆的attribute, 優先權以inline最大, internal其次, external第三(跟HTML裡include的順序有關), browser的預設值最小.

星期一, 8月 16, 2010

App Engine心得

現在試著用App Engine + Closure Library寫一個小程式 (暫時放棄django了, 花了一段時間比較到底用helper好還是用patch好. 兩邊都有擁護者. 等我熟一點後再來自已判斷吧)

所以又到記流水帳的時候了,把一些我在寫的過程中搞不清楚, 要查資料的點記錄下來, 希望之後可以查資料的頻率低一點.

星期五, 8月 13, 2010

Closure Template

Google還真的很多好玩的東西, 在Closure Library之後, 又研究了一下Closure Template.

用法跟之前玩PHP的差不多, 最大的差別是, 這個template寫好之後, 居然是要用一個Java程式去compile成Java script, 再直接給Java script程式呼叫. 應該是為了不要有太多執行時期的字串比對跟替換, 所以採用這種方法.

用法很簡單呀, 先寫一個副檔名為.soy的文字檔, 它將是template的source.
在它的第一行, 必需寫成
{namespace xxx.yyy}
其中xxx.yyy就是以下整個template的namespace. 搭配上之後定義的template, 在Java script裡就可以直接用xxx.yyy.zzz()這種方式來呼叫.

/**
* Says hello to the world.
*/
{template .helloWorld}
Hello world!
{/template}
這是最簡單的一個template了, 它定義了.helloWorld這個template. 在Java script裡就用xxx.yyy.helloWorld();來呼叫, 就會傳回Hello world!這串字.

document.write(xxx.yyy.helloWorld());

星期四, 8月 12, 2010

Closure Library tutorial心得

教學網頁: http://code.google.com/intl/en/closure/library/docs/tutorial.html

心得:
  1. document.getElementById('div id');
  2. function定義後面要加;
  3. goog.dom.createDom(tag, attr, childptr);
  4. Java Script prototype!! 難懂的一個概念. 現在大概的理解是用Function new出來的object, 如果要他們有一個跨object的method, 要加prototype字樣來指定. (這句是什麼鬼啊? 自己都看不懂.)
  5. goog.dom.appendChild(parent, child);
  6. goog.ui.Zippy(title, content);

星期三, 8月 11, 2010

Closure Tools的用法

Closure Tools包含了三個部份
  1. A JavaScript optimizer
  2. A comprehensive JavaScript library
  3. An easy templating system for both Java & JavaScript
它的官方網站在: Closure Tools
Google I/O 2010的介紹影片:

Closure Library使用方法
  1. 在你的project目錄下, 打"svn checkout http://closure-library.googlecode.com/svn/trunk/ closure-library-read-only
    "
  2. 會透過svn到Google code的server上抓回它最新的source. 放在closure-library-read-only目錄下.
  3. 寫一個簡單的java script檔, 例如hello.js
  4. goog.require('goog.dom');
    
    function sayHi() {
    var newHeader = goog.dom.createDom('h1', {'style': 'background-color:#EEE'},
    'Hello world!');
    goog.dom.appendChild(document.body, newHeader);
    }
  5. 再寫一個簡單的HTML檔, 例如hello.html
  6. <html>
    <head>
    <script src="closure-library/closure/goog/base.js"></script>
    <script src="hello.js"></script>
    </head>
    <body onload="sayHi()">
    </body>
    </html>
  7. 結果再用browser去開hello.html就可以啦.
這是最簡單的方法, 但效率會比較差. 因為Browser在讀hello.html時, 會再另外建兩個connection去抓base.js跟hello.js回來. 而hello.js裡的"goog.require('goog.dom');", 會再多建幾個connection去把對應的檔案抓回來. 一來一往, 互相還有dependency, 無法平行同時開幾個connection去抓, 速度就慢了.
Closure Library為了解決這個問題, 它還提供了一個Dependency Calculation Script. 用法如下.
  1. 執行calcdeps.py
  2. closure-library-read-only/closure/bin/calcdeps.py -i hello.js -p closure-library/ -o script > hello-calc.js
  3. 這樣就會產生hello-calc.js這個檔, 看看內容, 它把前面說的base.js跟其它因為goog.require()會被包進來的java script檔, 全部都放到hello-calc.js檔裡. 所以在hello.html裡, 就不用分別include base.js跟hello.js, 只要include這個新的hello-calc.js就好了!
不過看看檔案大小, 這個新的hello-calc.js還是有256k這麼大. 看看內容, 裡面有一堆Apache license的條文, 而且出現了12次! 這些當然都是註解, 不過也會佔用傳輸的時間, 所以Closure Tools在這個script裡, 更進一步提供一個compiler的參數, 可以把hello-calc.js變得更小一點.
  1. 下載Closure compiler. 這是一個zip檔, 解壓縮後把compiler.jar放在project目錄下.
  2. 執行calcdeps.py
  3. closure-library-read-only/closure/bin/calcdeps.py -i hello.js -p closure-library/ -o compiled -c compiler.jar > hello-compiled.js
  4. 如果執行環境有支援Java 6的話, 應該可以順利跑完, 並且產生hello-compiled.js檔. 這個檔案只有56k, 而且功能跟hello-calc.js完全等價. 原本的hello.html只要include這個檔就可以, loading時間可以瞬間變成1/4.

星期二, 8月 10, 2010

App engine

一直對App engine有興趣, 也寫了一些小小不成樣的程式自己玩. 在Google I/O的時候Google說他們內部用的CloudCourse open source了! 就想花點時間來看看別人怎麼用Appengine來寫程式.
CloudCourse網站上把它的source code抓回來, 發現裡面用了app-engine-patch這個東西, 讓django可以用appengine的database.
再把這個app-engine-patch抓回來玩玩, CloudCourse是用1.1版的, 再到它的網站上去看看它的文件. 才又發現它已經停止support了, 要大家改用Django-nonrel這個project.
另外, CloudCourse還用到了Closure Library. 唉, 真是學海無涯呀...

星期一, 8月 09, 2010

vim的search

原來我錯的離譜!

在用vi的經驗中, 經常會覺得很奇怪, search有時按n會是往上跳, 有時是往下跳. 今天終於真相大白了, 原來一切都是我一廂情願.

我在vi裡經常是用#這個鍵來search同一份文件裡目前focus到的這個字. 我預期它的結果跟我在command mode下按/, 再打那個字一樣. 就在剛才想要追根究柢一下, 原來#這個鍵本來就是往上查目前focus的字, 而*才是往下查. 我用了這麼多年vi, 一直把它用錯了!

awk

每次寫script用到sed跟awk都要再查半天用法, 這裡當作筆記吧.
awk
ex. grep ^version: app.yaml | awk {'print $2'}   從app.yaml裡找出version那一行, 印出第二欄的內容. awk麻煩的地方是command要用'包起來. 永遠都記不住...

星期日, 8月 08, 2010

VIM in MacOS

在MacOS裡的VIM是沒有syntax highlight的, 拿它來看python的code總是一片黑白. 只要加一小段設定在/usr/share/vim/vimrc就好了.
set ai " auto indenting
set history=100 " keep 100 lines of history
set ruler " show the cursor position
syntax on " syntax highlighting
set hlsearch " highlight the last searched term
filetype plugin on " use the file type plugins