發表文章

目前顯示的是 2010的文章

垃圾新聞...

http://tw.news.yahoo.com/article/url/d/a/101114/11/2gzwm.html


公廁比垃圾桶多 德女孩驚奇!我想她畢竟是來學中文的... 她想講的應該是垃圾桶比公廁還少吧...

在米國看到的好玩東西

圖片
今年一月去米國出差, 在Staple看到的有趣東西.

想不到吧, 連破產要填什麼文件, 都有套裝軟體呢... 而且在文具行就隨手可得. 該說米國相當制度化了呢, 還是經濟有大問題了呢?

Python cheatsheet

admin panel

http://www.ourtuts.com/34-outstanding-admin-panels-for-your-web-applications/

admin panel都做這麼炫... 我真是太遜了...

Data store encoding issue

唔, 為了省空間, 想把一些放在app enginedata store裡的文字, 用zlib壓縮起來放到blob裡. 在壓的過程中發現一些exception. 找了一些方法, 現在大致可以運作了...

原本

import zlib

compressed = zlib.compress(log)  # 這行就會發生exception

現在改成

compressed = zlib.compress(log.encode('utf-8'))  # 這樣就可以了

但是在unzip的時候, 也要decode回來.

zlib.decompress(compress).decode('utf-8')

這樣內容才會對喔...

Python 的簡短寫法

python裡有時候我需要取得一個str的長度. len(a). 但是a有時候可能是None. 所以我就要

length = 0
if a:     length = len(a)
這樣子要三行吶.
後來得知可以這樣寫 length = len(a) if a else 0
cool!

Entity group

慢慢對App enginedata model有感覺了, 之前還習慣用SQL的時候, 總覺得要抓什麼都得用query, 所以在App engine裡也不自覺地動不動就用下面這三種方法來抓data, 即使只要抓一筆資料回來.

app engine datastore benchmark

app engine最難以適應的應該就是data store了, 它是基於big table做出來的一種分散式的資料庫. 因為是分散式, 號稱非常scalable. 不過也因為是分散式, 很多在relational database很直覺的功能都不能用. app engine還有每個request只能執行30秒的限制, 所以一些database更新的行為要分段做, 更增加寫程式的困難度. 寫的時候除了更小心一點, 我還想知道app engine到底寫data store有多慢. (或多快?)

在Mac裡也可以用git的autocomplete

在用ubuntu的時候, 下git command都可以按tab來自動補後面的參數. 甚至連branch或tag name都會自動幫忙找出來. 十分方便.

但是在MacOS下就沒那麼方便了, 雖然它的console環境一切都好, 但是就這個讓我覺得不是太方便. 忍耐了好一陣子, 終於決定一定要找出來為什麼.

Link

比想像中簡單, download一個script, 固定在.bash_profile裡去source它. 就OK了!

解了一個怪BUG

圖片
昨天解了一個很奇怪的BUG, 這個BUG若沒有各方的經驗, 在昨天那個moment, 水到渠成, 我想應該是誰也解不了.

用cron來觸發mapreduce job

GAE + mapreduce雖然好用, 但是老要用它那個簡單的介面來觸發一個job. 不能自動化的每天自動起來做些統計的事, 感覺挺蠢的. 一直在找要怎麼加, 才能在cron.yaml裡觸發. 終於被我試出來了.

首先, 先指定一個url給特定的handler. 最簡單就是在app.yaml把所有link都導到main.py.
app.yaml
- url: .*
  script: main.py

然後在main.py裡加一段
def main():
    application = webapp.WSGIApplication(...
        ('/tasks/summary', SummaryHandler)],
        debug=True)
    util.run_wsgi_app(application)

重點就是這個SummaryHandler.

class SummaryHandler(webapp.RequestHandler):
    def get(self):
        name = 'count'
        handler_spec = 'main.process'
        reader_spec = 'mapreduce.input_readers.DatastoreInputReader'
        reader_parameters = {'entity_kind': 'main.Client'}
        start_map(name, handler_spec, reader_spec, reader_parameters)


當然啦, 前面要from mapreduce.control import start_map, 上面幾個變數, 就是在mapreduce.yaml裡的設定, 改成用程式來傳.

最 加一個cron.yaml, 內容是...
cron:
- description: daily summary job
  url: /tasks/summary
  schedule: every day 06:00
  timezone: Asia/Taipei

這樣每天早上…

CSS之Selector

以為把W3C School CSS看完, 而且考試考了95分, 就可以直接上寫幹活了. 結果才寫幾行就卡住又要查資料了. 問題在我的HTML長的像


<ul>
 <li></li>
 <li></li>
</ul>


我不想把所有li的屬性都改掉, 但我又不知道要怎麼用CSS selector去選id是userinfo裡的ul tag裡的li tag. 只好查資料囉. 最好的來源自然是w3.org囉.
Grouping
h1 {xxxxx}
h2 {xxxxx}
h3 {xxxxx}
跟h1, h2, h3 {xxxxx}是一樣的. 逗號隔開代表同時指定這幾種tag的style. Universal selector
*, 代表任何一種在document tree裡的element. Type selectors
這種最基本了, 任何一個HTML定義的基本tag.
h1 {xxxx} Descendant selectors
跟Grouping語法很像, 只是不用逗號, 改用空格.
h1 {color: red}
em {color: red}
h1 em {color: blue}





This is h1 here is em this is h1 again
會顯示成This is h1here is emthis is h1 againDescendant selectors
div * p代表div裡, 不管多深的p tag. Child selectors
body > p {line-height: 1.3}
代表body裡的第一層p child. 跟Descendant selectors很像, 差別是用>只會選到它的第一層直接child.Adjacent sibling selectors
這個一定很少用, 所以大多文章都沒有介紹到.
h1 + h2 {margin-top: -5mm}
代表選h1之後的第一個h2 tag.
h1.opener + h2 {margin-top: -5mm}
代表class是opener的h1 tag下的第一個h2 tag.Attribute selectors
[att], 所有有這個att的tag
[att = val], 所有att值是…

Meta-xx, 大都會失敗...

遇到一個問題, 自己沒有能力解決, 或是不想投資時間/人力來解決, 就得求助於外力. 而外力有很多來源, 自己又沒有能力做判斷哪一種最好的時候. 最簡單的做法就是統統都接受, 統統都採納. 這, 通常會失敗.

python怎麼sort dictionary?

為了做一個統計的圖表, 我對python的list操作又熟悉了一點.

這是要用server蒐集到的一堆資料, 做幾張圓餅圖. 那些資料會被統計為"A發生n次, B發生m次, C發生i次, D發生j次", 以此類堆. 可能有數十到數百種, 每個的發生次數不一, 從個位數到幾千幾萬都有可能.

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

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

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

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

- url: /mapreduce(/.*)? script: mapreduce/main.py login: adminStep 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 job…

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

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


interview

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

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

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

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

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

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

CSS之二

很多屬性都有分top, bottom, left, right. 通常可以合在一行寫, 有四種組合. padding: 25px 50px 75px 100px (上25, 右50, 下75, 左100)padding: 25px 50px 75px (上25, 左右50, 下75)padding: 25px 50px (上下25, 左右50)padding: 25px (上下左右都25)Grouping 可以用逗號隔開幾個selectors, 這幾個的效果是一樣的.h1,h2,p { color: green; }Nestingp { 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; }

CSS之三 Positioning

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

買GMail空間了...

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


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



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

CSS之一

現在在施行混亂學習大法, 寫到哪裡卡到哪裡, 卡到哪裡學到哪裡. 今天是卡在CSS上. 有個簡單排版的效果我做不出來, 查了好一陣子. 最後還是在PTT上問到答案... 在這裡記錄一下CSS我在W3CSchool做了啥.CSS是Cascading Style Sheet的縮寫 (話說cascading出現在我的碩士論文裡很多次)HTML本來不是設計來做排版的, 而是設計來描述一篇文章的結構. 例如head, title, paragraph等等. 用font, color來做一些效果, 一直都是問題.在HTML 4之後, 號稱可以把這些描述怎麼畫內容的方法, 都獨立於HTML之外, 寫在css檔裡.selector 跟 declarationsselector有幾種方法, 最簡單的就是統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>…

App Engine心得

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

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

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());

Closure Library tutorial心得

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

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

Closure Tools的用法

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

Closure Library使用方法
在你的project目錄下, 打"svn checkout http://closure-library.googlecode.com/svn/trunk/ closure-library-read-only
"會透過svn到Google code的server上抓回它最新的source. 放在closure-library-read-only目錄下.寫一個簡單的java script檔, 例如hello.jsgoog.require('goog.dom'); function sayHi() { var newHeader = goog.dom.createDom('h1', {'style': 'background-color:#EEE'}, 'Hello world!'); goog.dom.appendChild(document.body, newHeader); }再寫一個簡單的HTML檔, 例如hello.html<html> <head> <script src="closure-library/closure/goog/base.js"></script> <script src="hello.js"></script> </head> <body onload="sayHi()"> </body> </html>結果再用browser去開hello.html就可以啦.這是最簡單的方法, 但效率會比較差. 因為Browser在讀hello.html時, 會再另外建兩個connecti…

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. 唉, 真是學海無涯呀...

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要用'包起來. 永遠都記不住...

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

Browser extensions...

記錄一下我用哪些Browser extensions吧... 不然電腦那麼多, 哪些好用都記不得...
ChromeScribeFireInvisibleHandGoogle TasksAwesome ScreenshotAutoPager ChromeFirefoxFirebugClosure InspectorVideo DownloadHelperUser Agent Switcher

保險

前一陣子有個保險員一直來找我, 保險公司跟我在公司的薪轉戶是同一家銀行. 我本來以為它是公司附近那個分行的人, 所以就答應她來看看我現在已經有的保單. 她只要看看我的保單的第一頁, 不管是不是她們公司的, 她都可以查得出來實際的條款是什麼. 然後分析好壞, 優缺點...當然啦, 為了要賣她們家的保險, 自然會說東也不足西也不夠. 不過這個可能太菜, 跟我說的數字裡有一堆明顯漏洞. 不知道是她話術不夠純熟, 還是我比較容易一眼看出來?在這裡列一下我覺得的問題, 供大家參考. 看是我的問題還是這是保險的基本原理.我有一個終身壽險保單, 年繳11萬多, 繳15年後就不用再交了. 保險金額每年會以2.75%的速度成長, 一直到我掛掉為止. 老實說這是我爸的人情保單, 所以也沒打算動它. 這個保險員一直說服我把它停掉, 改成她們家的投資型保單. 這個時候就有趣了, 她拿了一份印得漂漂亮亮的表, 說每年交保費六萬元, 就有600萬的保障. 年報酬率以8%來計算, 只要25年, 保障就破800萬了呢. 同樣的年數, 我原本的保單只有191萬元. 我對她只有一個問題, 呃, 其實是兩個. 第一個是她能保證每年一定至少有8%的報酬率嗎? 她說以基金來說, 8%算很簡單的. 而且如果用保險來買基金的話, 什麼不限檔數跟免手續費的, 更划算! 那我就問第二個問題, 所以這個方面我需要做功課, 看要買什麼基金囉? 她說她有她們銀行的分析團隊, 然後她會親自幫我看, 給我建議. 我聽了沒嚇死, 看起來就傻傻數字也沒什麼概念的人要幫我看基金. 科斯托蘭尼說的好, 投資無非是想乘著經濟成長, 讓手上的錢搭個順風車成長. 沒錢買車自已開(買股票), 也想買票坐公車(買基金). 這個方法最大的問題就是你不知道司機有沒有駕照! 基金經理人績效不好就被換, 造成他們重短期績效, 然後流動率很高. 現在連司機都不用自已選, 還有一個連車都不會開的人要幫我挑司機. 雖然我自己績效也沒多好, 但至少盈虧自負.我兒子的她也有幫我看喔. 我兒子才保了一點醫療險. 她說是階梯式的保費, 雖然一開始比較便宜一點, 但跟她們家的平準式保費, 從第一年到最後一年掛掉都是一樣價錢. 長久累積起來用他們家的比較划算. 可是我掐指一算, 我兒子原本保單前25年的保費也都沒變, 她們家的前25年每年還貴個700塊. 到第26年…

GMail要爆了...

圖片
來了快兩年的部門, 這裡寄信如流水. cc來cc去. 不必要的夾檔跟收信人一堆. 差不多半年, 我的GMail就要爆了...

酷吧, 我想看到這個訊息的人應該不多吧?
我整理了幾次, 試著把有大夾檔的信砍一砍. 不過對於7.xG的信來說, 一次砍個幾十幾百MB好像沒什麼用, 所以我最後決定等到真的爆掉的那一天, 我就要花錢買容量了...

又去辦美簽了

這次是第三次了.

每次去辦的過程都大同小異, 只是填的表是愈來愈複雜了. 這次是因為之前的過期了, 為了避免哪天又突然要去米國, 預防性的先去辦. 從進門到出來, 大約一個半小時. 感覺沒有像之前一樣人那麼多.
這種一關一關過的申請流程, 其實最好做optimize了. 現在流程已經tune的不錯了, 那些工作人員不停地喊叫只是為了提醒一些有點迷糊的人.
這次也有一個面試官員問一大堆問題, 讓被她面試到的人一直掏資料, 連在美國時唸的畢業證書都拿出來了. 本來我也會被她面試到, 突然出現一個男的又開了一個櫃台, 只問了我"為什麼你要去美國?". 一個問題就打發我了. 等著明後天拿護照囉.

修水龍頭

老婆一通電話跟我説洗澡間的淋浴龍頭壞了. 身為一家之主當然要扛起修復的責任. 馬上就知道昨晚的任務是什麼. 過程有點曲折, 紀錄一下...
步驟一, 去大潤發shopping, 去買一個新的水龍頭. 新台幣1499元. 步驟二, 去把我們家的總水管關掉. 這次有點笨, 跑到12F結果發現那個開關要用扳手才能關, 又下樓拿了手電筒跟扳手, 再跑上跑下一趟. 步驟三, 才把買回來的新水龍頭拆開就發現, 需要防漏膠帶. 家裡當然沒有這種東西... 所以又騎車出去找水電行買. 跑了三家, 不是關門就是沒賣... 還好最後在九點半多的時候還有找到店有賣. 步驟四, 跑回家把接頭都用防漏膠帶包好, 正要去拆原本的舊水龍頭的時候才又發現, 家裡那套IKEA的工具實在太迷你了... 扳手不夠大, 不能拆... 超級烏龍. 只好硬著頭皮去問鄰居有沒有, 可憐我那個口腔癌四期的鄰居拖著病體幫我開門, 幫我找工具. 幾個月沒看到他, 原來他一直在家裡. 現在變好瘦. 而且好像拿腿骨去補下巴的東西... 變得臉變型, 腳也不能太能走了... 不過找不到, 再硬著頭皮去跟樓下的借, 樓下的小孩真乖, 應門的時候還問我要不要吃西瓜... :p 步驟五, 用借來的扳手把舊的拆下來. 步驟六, 把新的裝上去, 鎖緊. 步驟七, 再上樓去把總開關打開, 特別先要求Fiona, 要用電話聯絡. 我開水的時候要跟我説有沒有漏水或是爆開. 還好一切無事. 步驟八, 完成!
最後步驟, 還扳手給鄰居... :p

煮綠豆湯...

哈... 上次去大潤發買東西, 在樓下的美食街吃了一個牛丼, 附了一小碗綠豆湯. 牛丼很難吃, 但是綠豆湯還不錯, 就想自已煮來吃...

所以當天除了原本要買的東西之外, 又買了一包綠豆跟一包冰糖. 回家煮...

一直放到昨天, 才興起念頭開始煮. 原本一直被唱衰. 不過只煮一鍋綠豆有什麼難的? 配方如下.

綠豆 一杯半水 12杯 (1:8)就是這麼簡單, 只把綠豆洗一洗, 再用上面的比例放著, 泡了兩個小時. (原本只要泡一小時, 結果睡著了). 泡兩個小時之後, 有些綠豆看起來都要發芽了, 變好胖...
然後就倒1.5杯的水給電鍋, 開始蒸. 大約蒸40分鐘.
蒸好之後就放著悶, 大概再放50分鐘. 開鍋.
開鍋之後再加四把冰糖. 我手小, 抓四把就是了... 丟進去溶掉.
當下就先喝了三碗, 剩下的冰起來... 讚!