2014年12月25日 星期四

用python讀入agilent (keysight) binary file

故事是這樣子的,最近拿到一些透過Agilent示波器(好啦你喜歡叫他Keysight也可以)讀到的資料,要對裡面的數字做分析,由於資料極大時他們會用自家的binary格式存檔案,要讀出資料分析就比較麻煩。
他們自家網站是有提供……程式來分析,可惜是用matlab寫的…
What The F.. Emmm, Ahhh, Ahhh, 沒事
總之我看到這個東西就不爽了,俗話說人活著好好的為什麼要用matlab。恁北想用python沒有怎麼辦,只好自幹啦。

其實整體來說滿簡單的,只是把matlab code 用python 寫一篇,python又比matlab 好寫很多。
比較值得提的只有一個,分析binary就不能不用python的struct,相關的內容可見:
http://yodalee.blogspot.tw/2014/03/python-structdex-file-parser.html

這次我再加上用namedtuple來處理,整體會變得很乾淨;例如它一個波型的header格式是這樣:
int32 headerSize
int16 bufferType
int16 bytesPerPoint
int32 bufferSize

那我就先定義好namedtuple跟struct的format string:
from collections import namedtuple
bufHeaderfmt = “ihhi”
bufHeaderSiz = struct.calcsize(bufHeaderfmt)
bufHeader = namedtuple(“bufHeader”, "headerSize bufferType bytesPerPoint bufferSize")

再來我們讀入檔案,直接寫到tuple裡,就可以用名字直接存取值,例如我們要跳過header:
bufHdr = bufHeader._make(struct.unpack(bufHeaderFmt, fd.read(bufHeaderSiz)))
fd.seek(bufHdr.bufferSize, 1)

是不是超簡潔的?一個晚上就寫完了=w=

人生苦短,請用python。

原matlab 網址
http://www.keysight.com/main/editorial.jspx?cc=TW&lc=cht&ckey=1185953&nid=-11143.0.00&id=1185953

原始碼在此,不過我覺得是沒什麼人會用啦orz
https://github.com/yodalee/agilentBin

2014年12月9日 星期二

Translate Qt translation file (.ts file) using Python and Google Translate

Pyliguist

A python script translates Qt ts file by google translate

Recently I'm working on project Qucs. This project only has a little group of developers.

The program got about 3000 entries need to be translated, which, however, no one wants to translate them. To translate them manually is a very hard, and time-consuming work. It makes me think of using Python to translate these text automatically.

Luckily, there do have an automatic tool: Python Goslate package.
It's very simple to use, just create a goslate object. Then you can call function translate to translate the text, like this:

>>>go="goslate.Goslate()
>>>go.translate(“worship”, “zh-tw”)
崇拜

I write a little script “PyLinguist” in Python, which use Python “xml” to parse Qt translation file. Then use Python package “Goslate” to translate the text.

It takes 30 seconds to translate 200 entries in test file, which is much faster than translate manually. Though there is some problem. For example it translate “Help” into “Save me” in Chinese, but generally it works.

The source code is here:
www.github.com/yodalee/PyLinguist

2014年12月1日 星期一

使用python 與Google Translate進行程式翻譯

最近Qucs Project有個德國佬加入,這個……一加入就做了不少苦力的工作,像換掉一些Qt3才支援的function,換個Qt4相對應的名字,他說他是用Xcode的取代功能寫的,老實說這個東西不是用sed就可以解決嗎(._.),不過算了,有人幫忙總是好事。

他後來又貢獻了一個PR,內容是把整個程式的德文翻譯加了一千多個翻譯,根本巨量苦力;同時他又開了一個issue,想要把德文的翻譯給補完,我覺得這樣一個一個翻譯有點太累了,雖然Qt 有linguist幫忙,可是其實還是很累,遇到沒翻過的,還是要自行輸入。

當下靈機一動,想到之前看過有人用Google Translate來自動進行Gnu Po檔的繁簡轉換,那一樣我能不能用Google Translate進行Qt 的翻譯呢?

為了這個我寫了一個PyLinguist的script,輔助工具選用的是Python的package goslate:
使用方法很簡單,產生一個goslate的物件後,叫個function 即可:
go=goslate.Goslate()
go.translate("worship", "zh_tw")
'崇拜'

同樣的,qt的翻譯檔就是一個xml 檔,python要對付xml也是小菜一碟,用xml.etree.Element即可,每個要翻譯的文字會以這樣的格式記錄:
<message>
  <source>Hu&amp;e:</source>
  <translation type="unfinished"></translation>
</message>
Source是原始文字,Translation則是翻譯文,如果還沒翻譯,就會在translation tag加上type=”unfinished”的屬性。

整體程式流程大概是這樣:

讀檔,把整個xml 讀到一個xml tree 物件裡:
self.tree = ET.parse(XXX.ts)
root = self.tree.getroot()

開始翻譯,這裡我設定self.maplist這個dict物件,記錄所有翻過的內容,這樣只要以後再次出現就取用之前的結果,省下網路回應的時間;之所以要在translate的外面加上try, except,是我發現goslate在翻譯OK這個字時,不知為何會出現錯誤,為了讓程式跑下去只好出此下策;如果找到翻譯文,就替代掉之前的文字並拿掉unfinished的屬性。
for msg in root.iter('message'):
  source = msg.find('source').text
  isTranslated = not (msg.find('translation').attrib.get('type') == "unfinished")
  if not isTranslated:
    if source in self.maplist:
      msg.find('translation').text = self.maplist[source]
      del msg.find('translation').attrib['type']
    else:
      try:
        text = self.gs.translate(source, target_lang)
        msg.find('translation').text = text
        self.maplist[source] = text
        del msg.find('translation').attrib['type']
      except Exception:
        pass

最後把程式寫出去即可,也是一行搞定:

self.tree.write(filename, xml_declaration=True, encoding="UTF-8", method="html")

結果:

目前除了輸出時如xml 的DOCTYPE宣告會消失,大致上的功能是可接受的,翻譯800行約100到200個翻譯文的檔案,大約30秒就翻完了,這之中可能還有一些是google translate回應的時間,這已經比人工還要快了不少。

結論:

感恩python,讚嘆python
老話一句:working hard, after you know you are working smart,翻譯這種事多無聊,丟給google做就好啦。

原始碼:

本程式(毫無反應,其實就只是個腳本XDD)為自由軟體,原始碼公布在:
https://github.com/yodalee/PyLinguist

參考資料:

1. Goslate:
http://pythonhosted.org/goslate/
2. python xml
https://docs.python.org/2/library/xml.etree.elementtree.html

2014年11月24日 星期一

使用git rebase 進行Pull Request 檢測

故事是這樣子的,自從我被加到Qucs project的專案小組,原本的管理員又因為博班進到最忙的時間開始比較少管事,變成我在管專案的Pull Request(PR,拉取要求)。
其實管就管,反正這個project 沒人鳥,平常也沒什麼PR進來;不過有PR進來的時候,還是要做適當的檢查,以下提一下幾個檢查PR的流程:

首先是把PR拉到本地資料夾,這部分參考github 的支援文件:
https://help.github.com/articles/checking-out-pull-requests-locally/

$ git fetch origin pull/ID/head:BRANCHNAME
其中ID 是github上Pull request 的編號,branchname則是你隨便取;這樣就會把網路上的提交全部拉下來,並創建一個新的分枝。

接著就要做點檢測工作,最重要的是所謂的阿蹦大神規則:每個提交都必須能編譯成功
這裡我會選用git rebase 搭配execute:
git rebase -i master –exec “make -C path”
git 就會在每個提交間插入一個執行make 的command,要注意git 在rebase 時的目錄位置是在專案最頂層的目錄(.git資料夾的所在),所以make 的路徑必須設好,不然rebae 會找不到make檔案,直接出錯;git會輸出下列的文件,在提交間插入執行命令,如果有提交不想要執行,可以手動移除掉。
pick 92c96a8 Add Xcode support to gitignore
exec make -C qucs/build
pick 0cdd379 Bugfix: LANGUAGEDIR
exec make -C qucs/build
pick 9a695b0 Skip Qt3 support for qucs-help
exec make -C qucs/build
execute的規則如下:
執行的指令如果回傳值非零,表示執行出錯,rebase 即會暫停在當前的提交,讓你有機會修正錯誤,可以使用git rev-parse HEAD來抓到當前的提交雜湊。

這樣就能放著電腦一直跑,反正出錯了就會停下來,表示這個Pull Request是有問題的,還不能合併到主線內。

2014年11月17日 星期一

使用autotool 編譯qt project

在寫這篇,我發現我曾經寫過類似的內容:
「使用gnu make編譯Qt 專案」
http://yodalee.blogspot.tw/2013/08/gnu-makeqt.html

總之,這次又是在qucs專案上遇到的問題,之前專案裡的使用者介面,不知道是哪根筋不對,竟然全部都是用手爆的啊啊啊!正好這個project現在進入巨量refactor階段,在改其中一個部分時,順手把其中一個使用者介面換用Qt的Designer來做。
結果,還要改編譯的autotool,讓它使用UIC解決才行,網路上找找沒什麼資料,只好印autotool的文件下來看,以下是我最後弄出來的Makefile.am設定:

首先,定義目標:此資料夾的靜態函式庫及它的原始碼:
noinst_LIBRARIES = libdialogs.a
libdialogs_a_SOURCES = xxxxx.cpp

原始碼後面可能有一大串,一般來說autotool有這樣有夠了,不過對Qt project,首先我們需要MOC: Meta object compiler將標題檔編譯為moc.cpp原始碼,並把它們加到靜態函式庫的原始碼中:
MOCHEADERS = xxxxx.h
MOCFILES = $(MOCHEADERS:.h=.moc.cpp)
.h.moc.cpp:
    $(MOC) -o $@ lt;
nodist_libdialogs_a_SOURCES = $(MOCFILES)
這會讓編譯器去編譯MOCFILES,找不到就用副檔名規則呼叫MOC產生.moc.cpp檔。

UIC比較麻煩一點,因為標頭檔不像原始碼一樣,會被加到編譯時的相依規則中,若像原始碼在相依規則裡,相依性不符時,Makefile會自動去尋找有沒有可以產生此相依的規則,如上面的.h.moc.cpp;但標頭檔就算全不見了,不設定的話Makefile也不會做什麼。
這裡我們使用autotool的BUILT_SOURCES來解,被加到這個變數的內容會優先被編譯:

UICFILES = ui_yyyy.h
BUILT_SOURCES = $(UICFILES)
ui_%.h: %.ui
    $(UIC) -o $@ lt;
noinst_HEADERS = $(MOCHEADERS) $(UIHEADERS)
如此一來就能順利的呼叫UIC幫我們產生標題檔了;不過含有%這種寫法是Makefile.am使用Gnu Extension達成的,因些在產生Makefile.in時會收到警告,如果不用這種寫法就只能寫明所有*.ui轉成ui_*.h的規則了。

rcc的話我是沒有用,不過它是將qrc檔轉成原始碼檔,因此估計使用方法跟moc比較像。

參考資料:
1. autotool BUILT_SOURCES:
http://www.gnu.org/savannah-checkouts/gnu/automake/manual/html_node/Sources.html

2014年11月4日 星期二

用python 產生未引入檔的報表

故事是這樣子的,最近我無聊的時候玩玩的專案
qucs 理想上這個project是要達成類似ADS的模擬軟體,很不幸的在功能上遠遠不足;project 開始的年代是2003年左右,當初應該是qt3 寫的,因為qt 支援不足那時候他們還自己寫qt 物件vtabbar, vtabbeddockwidget什麼的。
現在還有一堆qt3support的東西沒有清除乾淨,這整團又黏得死死得要一口氣清光,原作者去年有設法把它拿掉,弄了50多個提交之後沒什麼結果,物件繼承又弄得一團糟,十年累積下來的修改可以氣死人。

從一開始參與的時候,我就覺得這個project 很怪,怪在哪呢?無論是把Qt3拿掉升去Qt4,幫它加上新功能等等,不管你怎麼改,改了多少Qt的object進去,它編譯通常都會過,就算你沒include,它還是過了……
後來我才檢視到,在它最上層,位階僅次於main.h的qucs.h(光看名字就知道這有多核心XDD)裡,竟然加上了一行
#include <QtGui>
這…這行也真是霸氣外露,這根本是幫project加了個金剛不壞之身,之後所有的header files應該把qt object 的include都投去太平洋才是;這實在不是好習慣,QtGui 包含了太多的標頭定義,一方面會影響到編譯時間(下面連結有人說40%),同時也讓你抓不到每個檔案到底需要哪些標頭。

後來我用grep 下去掃一下,總共有兩個重要標頭檔被加上QtGui include,五個子資料夾d 重要標頭檔被加上這行,另外還有113個原始碼檔案。
如果要手動慢慢移除,大概會花上不少時間;也可以用sed 一個氣全移光,再來慢慢修,不管怎麼樣,移掉它們一定會產生一堆沒include標頭檔產生的 undefined error,要慢慢把該include 的檔案加上去。
老話一句:「working hard, after you know you are working smart」

為了這個問題,寫一個python code來解決。
問題很簡單:一但移除include QtGui,編譯時會產生一堆undefined error,我們要把該引入的標頭檔加上去,我的策略很簡單,用一個python script去剖析編譯的錯誤訊息,找去哪個檔案缺什麼定義,自動寫入暫存檔裡,產生該加上的include code即可。

呼叫make的地方就用python 的subprocess 模組,用make -k儘量產生各種錯誤:
from subprocess import Popen, PIPE
cmd = ['make', '-k', '-j8']
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
errormsg = str(stderr)
這樣我們就取到錯誤訊息了,stdout其實可以不理它。

這個project用的是clang,它的message 形式是這樣:
檔名:行數:字元數: error: unknown type name '物件名'
該行的原始碼
可能的錯誤訊息有unknown type name跟implicit instantiation of undefined template。

要剖析也很簡單,連regular expression都不用,用split直接切下來就是了,最後我們用字典建立檔案跟缺少的物件列表:
files = {} filename = line.split(':')[0]
classname = line.split(“'”)[1]
if filename in files:
    if classname not in files[filename]:
        files[filename].append(classname)
    else:
        files[filename] = []
        files[filename].append(classname)
這樣我們有報表了,再來就是產生一下引入的原始碼,如果是標頭檔,會產生class forward declaration跟include引入,原始碼檔就比較簡單,全部產生引入即可,如此一來就能輕鬆產生引入的程式碼。最後我們還能用subprocess幫我們打開vim,把有錯的檔案跟我們寫入的報表一起打開,就能輕鬆修正所有的錯誤。

結果:
我花了大約30分鐘的時間,把120個檔案的QtGui 引入全部刪完了,單核心編譯時間從原本的344秒加速到245秒,真的大約提速29 % OAO

相關資料:
1. Qucs 專案:
https://github.com/Qucs/qucs
2. QtGui相關討論:
http://qt-project.org/forums/viewthread/18766

2014年8月27日 星期三

使用git bisect 搜尋災難發生點

之前因為強者我同學阿蹦大神的關係,接觸了neovim這個大型專案,光星星數就有9300多顆,是我星星最多的project的9300多倍lol。
雖然說看了幾個issue,大部分都插不上話--討論的層次太高了,偶爾有個好像比較看得懂的,trace下去之後提出解法,沒想到是個不徹底的解法,pull request就被拒絕了TAT,要參加這個超過9000顆星星的project,像我這種花盆果然還是「垃圾請再加油」

--

雖然說是這樣,但我還是趁這個機會,研究一下如何使用git bisect 在project裡面找到洞洞。
基本上project無論用了多少test,多少還是跟我的腦袋一樣有一些洞,要如何找到洞洞就是一門學問了,git 提供了git bisect這個指令幫助開發者找到出錯的地方

我們用一個比較小的project: pyquery來實驗這個功能,這是強者我同學JJL大神參與的專案

https://github.com/gawel/pyquery

我們trace 一下issue 74: Behavior of PyQuery...
因為這個issue 發生在v1.2.4,但到了v1.2.9已經消失了,那我想知道這從哪裡發生的(這種狀況比較少見,一般都是有錯要找哪裡出錯了),就用bisect 來找吧。

首先是bisect 的基本設定,我們要先啟動bisect,然後指定一個good commit 跟一個bad commit,而bad commit 在歷史上要比good commit 來得晚,bisect 會從bad commit 一路回溯到good commit 為止。通常可以透過checkout tag的方式作大範圍的搜尋,以免bisect檢查太多commit,在這個例子中,我們發現v1.2.8->v1.2.9的過程中這個bug 被修掉了。

因此我們設定:
$ git bisect start
$ git bisect bad 1.2.9
$ git bisect good 1.2.8
Bisecting: 11 revisions left to test after this (roughly 4 steps)
[bc1b16509cec70de7a32354026443fca777f4d7d] created a .gitignore file(which is almost a copy of .hgignore with some minor changes and comments)

這時候我們已經進入bisect 狀態,用git branch的話會看到現在是(no branch)狀態。
要說明一下這裡的good, bad只是bisect上的一個概念,它會從bad 開始找到good,至於裡面是不是真的 good/bad,這由開發者決定。
這時bisect會checkout 處在good/bad 中間位置的版本,我們執行事先寫好的一個測試檔test.py,它會自動測試這個issue的狀態

from pyquery import PyQuery as pq
x = pq("<div></div>")
y = pq("<div><table></table></div>")
print(x.is_("table"))
print(y.is_("table"))

執行發現它還是回傳False/False,因此我們輸入
$ git bisect bad
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[b81a9e8a2b0d48ec0c64d6de14293dd4a680a20b] fixed issue #9

bisect 會以binary search的方式checkout 一個更舊的版本,然後你再測試一次。
經過五次的bad/good的測試結果,bisect回傳:
300cd0822505a4bd308acd1520ff3ef0f20f8635 is the first bad commit
commit 300cd0822505a4bd308acd1520ff3ef0f20f8635
Author: Gael Pasgrimaud <gael@gawel.org>
Date: Fri Jan 3 10:35:30 2014 +0100

fixed issue #19

:040000 040000 1d9cb3b170a8fdb2846e3c0e0fb6d2be9a9538d5 07d3a40ff73dda078d7543be2fab2f9f927b0c1f M pyquery

這樣就抓到這個 fixed issue #19 的commit 就是修好這個issue 的commit 了,最後要用
$ git bisect reset
結束bisect狀態。

--

上面這個方法好像還是不夠方便,理論上bisect 支援git bisect run這個方法,可以送一個script 給它,它會自動執行,並以回傳值0表示這個commit 是good,回傳值1表示這個commit 是bad,回傳值125表示這個commit 要skip掉。
所以我改了上面這個script 為:
import sys
from pyquery import PyQuery as pq
x = pq("<div></div>")
y = pq("<div><table></table></div>")
if x.is_("table") == False and y.is_("table") == False:
    sys.exit(1)
else:
    sys.exit(0)
可是不知道為啥,bisect run ./test.py的結果,每個commit 都會是bad的輸出…這真的是太奇怪了,我猜有可能會是git bisect的問題也說不定,有空再來詳加研究。

--

8/28增補:

後來經過阿蹦大神的指出,問題可能是出在*.pyc上面,因為python要是看到現在的pyc跟現在的時間相同,就不會更新pyc而是直接跑pyc。
git bisect run會極速的checkout 舊分枝,跑python script,看結果跑下一步;而pyc的檢定大概是用秒在算的,就變成python並沒有更新pyc檔,反而是用pyc跑出同樣的結果,bisect 自然出錯了。
解決方法有兩個,第一個是寫一個shell script test.sh,先刪掉所有pyc檔之後,再執行python script:
find . -name “*.pyc” -exec rm {} \;
./test.py
然後用git bisect run ./test.sh
第二個是讓python script 跑慢一點,讓python能察覺到python 的版本變化:
import time
time.sleep(1)
第三個應該才是根本的解法:
在python 的shebang上面加上 -B的參數就好了
執行結果就跟手動的一樣了,去你的pyc。

結論:

bisect很好用?不是,我認為從這個案例中最重要的概念,其實是自動測試的重要性,如果程式能保持一個自動測試的script,在除錯上可以透過script 自動找到錯誤點,不需要人工手動介入,試想若每個commit都需要手動10步驟的測試,兩個版本間有10個commit ,測試步驟立刻變成100步,但用script只要一個指令就能知道是好是壞,搭配bisect才能事半功倍。

參考資料:


Git-bisect doc: http://git-scm.com/docs/git-bisect

2014年8月22日 星期五

Git-flow 簡介

最近因為工作的關係接觸了git-flow相關的內容,在這裡就介紹一下git-flow的相關概念。基本上git-flow就是一個git 的擴展,把一群git 指令集合在一起,更方便管理人的操控,如果去看它的執行檔,其實就是一個shell script,所以使用git-flow時也可以用git 指令,同時只要熟練git的話,就算不用git-flow 也能操作自如。

我認為git-flow最重要的還是背後那個分枝的規則,我覺得學起這個規則就好,我們就先討論它設計的理由,同時搭配相關的git 指令:

git-flow會有五個主要的branch: master, develop, feature, release, hotfix,以下一一介紹:

有master branch是當然的,master branch是要讓使用者使用的,使用者checkout project時就要看到的內容,master branch上的commit 應該加上tag表示軟體的版本。
$ git tag -a v0.1 -m 'message here'

因為是要讓使用者用的,所以平時自然不能隨便在master 上面修修改改,開發者要先換個 develop branch上面進行開發。
$ git checkout -b develop
or
$ git branch develop && git checkout develop

git 允許許多開發者一同開發這個project ,如果大家都一股腦往develop 上放東西,每個開發者都會被commit 時的衝突問題煩到死,因此要開發一個新的feature,就要新建一個feature 分枝。
開發完時,這個分枝再併回develop 上:
$ git checkout -b feature-issue42
git commits
$ git checkout develop && git merge –no-ff feature-issue42
這個部分應該是最花時間的,通常會遇到共同開發的pull/push也是在這個部分,這裡不贅述,就請參考之前的文章:

軟體開發到一個程度,就進入release 流程,從develop 切換到release中,停止新增feature,開始專注在修bug 跟改文件等等工作上,準備就緒後,就外送到master 跟送回develop 中。
$ git checkout develop && git checkout -b release
git commits (only bugs)
$ git checkout master && git merge --no-ff release
$ git tag add -v0.2 -m 'message here'
$ git checkout develop && git merge --no-ff release

最後,沒有軟體是沒問題的,如果master上被檢出需要立即修補的重大問題,這時就要動用hotfix,把master 分枝出hotfix branch,修完後再併入master 和develop中。
$ git checkout master
$ git checkout -b hotfix
fix bugs, commit
$ git checkout master && git merge --no-ff hotfix
$ git tag -a 0.2.1 -m 'message here'
$ git checkout develop && git merge --no-ff hotfix
$ git branch -d hotfix

在文中的merge 指令都有使用 no fast-forwarding的--no-ff 指令,這是為了保留一個分枝跟合併的 記錄,以免fast-forwarding造成所有branch全混成一條。
當然這個流程只是參考,事實上接觸的幾個project幾乎都沒有照這個流程,大部分都是把master當成文中的develop在用,一樣分出feature來開發但沒有release,然後hotfix branch就是用master一路往前修。

所以說,感謝大家花了幾分鐘看了這篇廢文XDD

2014年8月17日 星期日

我與HDE

故事要從五月開始說起,那時候參加了pycon Taipei 2014,看著台上眾多大神的報告,覺得自己真是一個花盆。不過,在進場的小袋子裡,除了會議時程表外,還有一些其他的東西,像是可愛的github小貼紙,另外還有一些求職傳單。

其中,就有我將要開始實習的HDE。

--

回來的時候也沒想這麼多,雖然平時我都有寫一些程式,但是我研究所念的東西跟軟體還是想差太遠,如果畢業之後要進到軟體業的話,還是需要一些實戰經驗,我定下兩個方向,一個是參與free software的開發,另一個就是參與實習。
那時候大概把找得到的暑期實習機會都投過了,很幸運的,HDE竟然回應我的申請。

第一階段是直接考程式,第一題要寫一個簡單的數字處理程式,可以用python,Erlang,C++,Ruby之類的。
個人是覺得還滿簡單的,用python解決輕鬆寫意( ̄▽ ̄)-|_
第二題比較機車,跟網路有關,要用python的httplibs去解,這時候就要瘋狂查網路資料lol,我懷疑如果是當面考的話我應該寫不出來,拜google大神才順利寫出來,實在有夠廢。

--

後來通知Skype面試,人生第一次Skype面試呀
結果對方打電話過來,我的Skype就當機了= =,莫名奇妙,「你爸沒教過你不要在人家第一次面試這樣搞嗎?」 
面試是用英文(如果是日文的話我大概會直接GG)記了一些問的問題,僅列如下,順便附自己的回答:
*請簡介一下你自己?
A喔這好像是萬年老梗了,結果我還是答得亂七八槽(T_T)

*可以說明一下你有什麼experience跟internship?
A恁北網管這樣算嗎?

*請說明一下你的生涯規劃,有想要在哪裡工作嗎?台灣、日本、韓國、Bay Area…
A吾乃魯蛇,不要求什麼國家,只要能有工作,然後能有時間持續充電,我就不排斥
(是說這樣是不是刪掉不少台灣公司…?不過我真的認為持續充電很重要呀)

*請說明你這個人有什麼優勢?
A本回答已被QClean屏蔽

*請說明你這個人有什麼劣勢?
A本回答已被QClean屏蔽

*請說明你未來職場上的規劃?我看你大學是念微波的,未來呢?
A我認為這算我的劣勢之一,未來想走軟體路線可是念的是硬體
所以目前我努力找軟體Intern,參與free software project,就是要證明我有軟體能力…

*本問題已被QClean屏蔽
A滿新奇的呃啊哈哈,我還有借機車來環島啊哈哈,還要適應各種交通狀況

*所以你會說日文嗎?
A一點點吧,讀跟聽比較沒問題,寫跟說就會GG

--

另一個面試官

*我們來點技術性的,首先看到你mission 1,你用python寫的,可否說明
A嗯,題目要求可以用C, Erlang, Go, Python, Ruby,其中我會C跟python
我選Python,因為……因為寫起來比較快嘛(生命苦短,珍惜生命,請用python =w=)。

*請問你大概花了多久?
A約30分吧我猜…

*那如果用C來寫呢?追問:那C++呢?
A我想都可以的,我應該會一點C++
按:老實說這裡我忘了跟他們確認是第一題或第二題了,要是是第二題的話我大概不會QAQ。

*請問你有寫過網頁App或是網頁service嗎?
A沒有TAT

*那請問有自架網站過嗎?
A我曾經用php mySQL架過一個測試用留言版,跟個人網頁,不過只能從自己電腦連線
如果要夠安全,能夠公開,大概有點難度

*現在要你架一個網站server,你要多久
A幾小時吧,要完全的安全大概要更久

*請問你熟Configuration Management or Continuous Integration
A我目前參與的github project有使用Travis CI,不過我本身是沒用過啦(yay)

--
我們的問題到這邊,請問你有什麼問題?
Q2:本問題已被QClean屏蔽。
本回答已被QClean屏蔽

Q1:請問本司預計招多少個Intern呢?(這類問題好像是禁忌?)
本回答已被QClean屏蔽

公司的地址在渋谷。
BGM: Welcome to Tokyo:
住處的話公司推薦我去找Sakura house,專給外國人在日本的短期住宿,後來找到的房子在代代木公園(yoyogi Koen),跟渋谷、原宿大概成一個正三角形,經過代代木八幡站後面就是代代木公園跟明治神宮,晚上可以出去慢跑一圈,感覺挺好的。

HDE Intern的規定是每月有150000 JPY的薪水生活補助,另加保險與來回機票,這1.5勝文150K JPY……呃……它是寫「這不是薪水,而是生活費的補助」網頁的解釋是說:
...not for work (because the program are not for work, to comply with the visa regulation) but for your living costs (food/ traveling expenses/ apartment).
在沖繩留學的同學也解釋,這是因為「日本規定沒有勞簽證,不能拿正當的薪水」,至於當中有什麼差異,也許我再跟他們請教
啊老實說我是感覺很有趣,廣義上來說這就是薪水呀,它這樣講就感覺就是給了錢然後說:「這……這才不是給你的薪水呢≥ ≤。」什麼奇怪的傲嬌XD

--

然後我訂機票又訂到華航松山-羽田的機票,比起桃園-成田的機票…呃…貴了3K,這我得辯解一下,買華航是因為他的飛行時間比較正常,中午就可以到東京,這樣下午才有時間辦入住;然後看google map羽田比成田離東京比較近嘛,誰想得到一個城市兩個機場,一個機場比另一個機場貴3K啦(╯-_-)╯ ~╩╩

人生第一次坑人錢就坑3K,我真的不是故意的啊O_O

--

另外,因為「Yoda言論自我審查」的關係,與HDE相關的內容在我的Facebook上會儘量屏蔽,畢竟在下也是位延畢生,之前同學口試通過啦、出國去conference啦、各種畢業證書照啦、出國去大學課程或是不然就各種去玩啦,深知一群人用「過得很爽的感覺」的內容洗別人版,叫我這種花盆情何以堪,因此Facebook上將進行言論管制。

事實上有關實習之前都是列機密,知道的應該在五十人左右。

至於是在東京,知道的人數,嗯,大概是十來位吧,感謝大家幫我守住祕密,沒有四處聲張,至於我幹嘛不說在東京……因為……因為你們沒問啊 /人◕ ‿‿ ◕人\,而且我其實有說我在東京吼,你看我有發一則'welcome to Tokyo'的連結(炸)。

我記得暑假初期有一本書,是講當社群網路跟鄉民文化發展到極致時,世界上會出現多麼光怪陸離的事情,女主角一開始不願意在社群網路上分享東西,於是有了這段對話:

「這是一位臥病在床的小孩,她也許想看到妳看到的美麗海面和滿天星斗,妳不分享你看到的,等於是在傷害她們,剝奪她們看到這樣風景的權利。」還有一段總結是:
「祕密即是謊言;分享即是關懷;隱私即是偷竊」
嗯這個,請大家不要讓世界變成那樣,有事不發到Facebook好像變罪過一樣;請大家將花盆比花盆,營造低調Facebook環境。

--

同時話說回來,我也不覺得在日本工作算是什麼值得炫耀的事情,強者我同學要不是好幾年前的暑假,當花盆我還在各種耍廢的時候,就開始各種像101、日月神教、法國實驗室的實習了,現在還有同學直接在灣區工作,花盆現在才在人生第一次實習,差這幾年的時間根本悲劇,老早就看不見大家的車尾燈了。

總之,實習正式展開,希望花盆能活過這一關。

相關連結:

1.HDEwebsite:
HDE.co.jp
2.HDE Intern website:
http://www.hde.co.jp/gip/
3.SakuraHouse:
http://www.sakura-house.com/

2014年8月7日 星期四

使用sed取代ADS檔案路徑

最近實驗室正在畢業潮(已羨慕),學長們約定俗成要把自己的設計燒成一片光碟傳給學弟……喔或是學妹。
一般習慣不好的話,在ADS 的設計檔裡,會包含很多絕對路徑的內容,這樣這個設計project就變得難以移植。
以我隔壁超強的同學「瓦哥」為例,過去的電磁模擬記錄會這樣寫
D:\Program Files (x86)\Sonnet\0.18um_m\transformer\PA\sonnet\Stack_PA\XXX.snp
移到別的電腦就找不到這些電磁模擬檔。

比較好的做法是把電磁模擬放到ADS的project資料夾內,例如新建一個EM的資料夾,然後用相對路徑去存取:
EM\Stack_PA\XXX.snp
就能確保模擬檔的可移動性。

那如果已經做完了,難道要一個一個改嗎?
ADS的設計是記錄在dsn文字檔裡面,這類文字檔的操作其實也很簡單,在ADS project的networks資料夾,改掉dsn裡面的檔案即可:
用sed 一行解決,加上for loop 輕鬆寫意,就跟喝水一樣輕鬆:

for i in *.dsn; do sed -i 's/XXX/yyy/g' $i; done

缺點:Unix 限定……,windows我還真想不出解法,可能要用python, mingw,不然powershell可能有類似的功能?
當然要一個檔案一個檔案打開來改也不是不行,只是很不smart就是。

2014年8月1日 星期五

無意間做了不得了的事呢

7/31晚上本來還在練日文聽力,卻瞄到FB(謎:練聽力不專心,拖出去砍了)一兩位高雄的朋友在貼出家門口發生爆炸、或是聽到巨大爆炸響聲的消息,照片跟影片有點猛,根本就是watch dog實況飛機轟炸了。
後來幾條即時新聞貼出來,看到一兩個爆炸點離我家好近,發條簡訊回家問候,沒想到家人回電說離家不到50公尺的馬路整個爆炸,現在家裡都是瓦斯味,整條街的人都疏散到附近的學校操場了。

從這時開始追蹤BBS上面的消息,發現爆炸範圍大得誇張,一堆路口都有爆炸的消息,一開始消息很亂還一度有新聞說前金區都有爆炸(後來更正是感覺得到震動)

後來發現沒人好好整理一個爆炸點圖,只看文字實在不知道哪裡發生事情,經過好友qcl大神的指點,用了google map engine,憑著新聞上的路口報導,網友提供的圖片影片,對照自己生活18年記下來的腦中地圖,大略畫了一張高雄的救災地圖:

後來在Facebook和BBS上被廣泛轉貼,大概是我做過最多人看的東西(我猜應該是用萬當單位的吧),一度流量大到我自己都不能編輯,今天新聞網頁也都有放地圖的連結。
不可否認做地圖滿累的,要不斷掃視即時新聞跟BBS的發文,判讀照片、影片的位置,救災單位的消息出來也要更新上去,後來3點多看事件差不多平息了才上床睡覺。

一天一夜的驚濤駭浪,要感謝強者我同學qcl,寄信跟丟水球提醒資訊更新的網友,整理住宿地圖資訊的網友;最後還要感謝提供平台的google map ,據說還引起google內部工程師的注意,把地圖的流量上限往上調,這個即時調動頻寬的能力真是世界一流啊OAO

結語,該怎麼說呢?
很有幸我們生在這個時代,網路讓每個人都有機會對資訊貢獻一點心力,而正如上一篇對Uber的評論:
「資訊有效的傳遞,是很值錢,甚至攸關性命的」
但網路再有效也有它的極限,現在市府已經進場救災,更有效的指揮體系已經建起來了,這張地圖也差不多可以功成身退了;進一步的原因追蹤不是坐在電腦前抓得出來的,但有幸能宅在學校,對家鄉提供一些心力,個人表示十分榮幸,做了一個大家都在看的地圖,大概就跟「qcl誠徵女友」
http://qcl.github.io/qclwgf.html
一樣,無意間做了一件了不得的事,我自己也滿驚訝的。

ps: 要是我寫的code也有這麼多人看就好了(炸)

2014年7月14日 星期一

我看Uber,法規與科技之爭

最近據說Uber 大舉入侵台灣,又是掀起一波爭議,網路也是各方意見都有:有認為是自然市場競爭的;有認為對計程車是壓迫的;也有說法認為Uber完全沒有任何創新,結果被嗆爆的。
對這個問題,我也來寫寫我的想法,反正這個blog基本上沒人在看,寫再爛也不會被嗆爆,剛剛講的幾篇都在參考資料,讀者請視了解程度自行觀看。

我覺得要討論這個問題,有很多方面可以著手,也許可以先從網路來講:網路最值錢的地方在哪?
我說:是資訊。
網路用一種前所未有的方式在傳遞資訊,而資訊是值錢的!小如產糧地發生水災,食物可能會上漲,要先買食物放著;大如敵軍正在朝哪裡行動,我們要如何因應。古代的情報偵察要是看到網路大概會興奮而死,好好利用網路帶來的資訊,已經在無數產業掀起變革。

最簡單的,以前的商品買賣,是商家進貨,看看有沒有人要買,沒人買東西壞了就是商家賠錢。現在東西透過網路在賣,有需求再進貨都行,需求和供給間的資訊差被弭平,資源能更有效的利用。
以前找人才,是發個分類廣告,期待有人看到;現在用求職平台,可以接觸到全世界的人才,求職與求才的資訊更有效的整合。
還有很多!颱風來了:從網路新聞得知明天飛機取消,不用再跑一次機場,節省幾千位旅客的時間;從網路知道明天颱風放假,就不用浪費時間跑去學校(台北市不適用);用網路架平台,把颱風受災資訊全丟上去,政府就知道如何分配救災資源。

資訊有效的傳遞,是很值錢,甚至攸關性命的。

那我們來看計程車這個案例:
以前司機不知道乘客在哪,只好在市區不斷繞行,或者去人多的地方排班;以前乘客不知道司機在哪,就在路上招車,或者在排班點上車,兩樣都是無效率的體現,司機可能怎麼繞就是載不到客,乘客可能怎麼招就是招不到車。
Uber用App媒合司機與乘客,有需求就發車,比原來的計程車更有效率;我甚至還聽過其他叫車服務的玩法,允許乘客設定小費的價格,下班時間你想快點招到車,小費加一倍車子立刻就來。
我會說Uber讓載客服務的「供需」變得更平衡,靠得就是資訊的力量。

好但是問題來了,為何我會說這是「法規與科技之爭」呢?

再回到前面的「資訊差」裡,計程車跟乘客的資訊差不止如此:
1. 乘客很可能不知道路,司機可以繞遠路多收錢。
2. 乘客根本不知道開了多遠,那雙方要怎麼知道該付多少,司機可以任意開價嗎?
3. 如果有不良人士假扮司機,其實是要隨機擄人勒索呢?
有資訊差存在,就有可能產生不公平的投機管道,或者合約雙方產生責任義務不明的部分,政府需要提出管理辦法:以下面的參考資料來看,可以看到有重大前科者不能從事計程車業;要開計程車要先行登記;收費有公訂的跳表,給乘客跟司機一個公平的參考。
這些法規基本上都是針對計程車司機而來,就是要平衡司機在資訊上的優勢。同樣的,賣家必須給七天的鑑賞期、政府訂定的定型化契約、銀行準備金的規範,都是在對資訊優勢的一方進行限制,以防資訊優勢的濫用。

但現在,Uber已經利用科技弭平司機與乘客間的資訊差,乘客現在可以用google map查證路線正確與否;用信用卡付款查驗司機是否超收;以評分的方式對不良司機進行檢驗;相形之下,法規加諸司機的規範有些已經過時,資訊的天平倒向乘客一方了。

就這個爭議來說,乘客、司機、政府三方,我認為該進步的是政府的法規,Uber是利用新科技提供的新服務,正面的解決過去載客服務遇到的問題,如何提出新的辦法來管理司機的素質?是否開放乘客與司機自由訂定費率?新科技總會帶來新的變革,政府要如何將新的科技融入過時的法規當中,解開老舊不必要的枷鎖,正是解開Uber與計程車衝突的關鍵所在。

參考資料:
Uber 基本介紹:
http://www.appledaily.com.tw/realtimenews/article/new/20140712/432100/

2014年7月3日 星期四

在64 bits OS上編譯nasm 組合語言

最近作者正在看nasm,某個assembly 的實作,因為作業系統都升到64 bits了,要編譯asm code需要一些額外處理,以下記錄一下處理步驟,我是用archlinux,不過我想其他作業系統應該也差不多:

首先作者有提供asm_io.asm,這要先編譯,先安裝作者的nasm組譯器:
sudo pacman -S nasm

組譯:
nasm -f elf -d ELF_TYPE asm_io.asm
nasm -f elf first.asm
這裡的first 是我們自己寫的asm code

下一步要用gcc,原本書中是建議
gcc -o first driver.c first.o asm_io.o
不過方才都是用elf32去組譯的,所以要改成:
gcc -m32 -lc -o first driver.c first.o asm_io.o

這裡要安裝:
sudo pacman -S gcc-multilib gcc-libs-multilib
然後我還遇到找不到shared library libisl的問題,可能是gcc-multilib跟不上isl的更新,這個用symbolic link到libisl.13.0.0的方式解決

之後就可以完成編譯了,不過也許學著寫64 bits的assembly比較治本?

2014年6月28日 星期六

自己犯的錯自己刪,使用git-gc

最近我修改了我的ADS2Origin,因為使用者回饋表示,有時候資料區塊長度不同是無可避免的,比如說遇到loadpull的圖形,因此我把輸出改為csv格式,程式只會提醒使用者資料區塊長度不同,而不會自動切掉長度過長的部分;這個東西其實也不難改,反正資料就在那裡,只是改一下寫出的方式。
倒是寫這個讓我想起data mining的名言:「做data mining的,用了70%的時間在處理資料,30%的時間在靠北處理資料」

與此同時,很高興6/25號晚上我又推了一位同學當使用者,使用者人數++。
為了方便使用者,把下載連結換到dropbox的公開連結上:
https://dl.dropboxusercontent.com/u/3192346/ADS2Origin.zip

--

另外,最近我發現到一個問題,因為我的git project把windows下的執行檔都包進去,git又是每記錄一個版本就把檔案都複製一份,看一下我的git repository已經14 MB(唔…跟某些project用幾十G在算的比起來其實還是很小),不過恁爸保留exe的commit好像也沒啥用,就趁這個機會研究一下怎麼刪掉舊記錄裡面的執行檔。
不能用git rm ,這是不夠的,git歷史資料還是會保留著,因此需要一些特別的方法,主要的參考資料是參考資料一的:「Git 內部原理 - 維護及資料復原」,其實大部分的內容它都講完了,我只是照做而已。

其實理論上是不能這麼做的啦,這樣的行為會改變整個有大檔案存在的歷史,在有協作時需要你的團隊重新拉你的commit,會如此麻煩是因為git的設計理念就是不讓你輕易的丟失資料。
不過不管啦,我有幾個理由:
一、這個project根本沒人理
二、恁北我看windows不爽,就是要把windows的執行檔幹掉
三、跳脫舒適圈

首先看一下project的狀況,在執行完git gc後,再用git count-objects -v看看project有多大:
得到size-pack為: 3350 KB
我們的目標是一個名為dist的資料夾,裡面放滿了py2exe產生的巨量檔案。
用git log找出所有有加入該檔的歷史資料:
git log --pretty=oneline --branches --abbrev-commit -- dist
這個的會列出所有head下,match到dist 這個路徑裡的log,使用縮短的sha來顯示,結果如下:
5f9f3dc output in csv format, allow various length data
23f8633 windows executable file of 0.3.1 version
bb1107f Merge branch 'master' of github.com:lc85301/ADSToOrigin
e891091 update ADSToOrigin.exe version
acbeb1d fix duplicate tital bug
5343e5c add data length different detect, multifile sup
9ff12b9 multi variable parser support add
c989cc4 allow drag in windows
b21d5c1 windows distribution
的確,第一次把dist這個資料夾加進來就是從這個windows distribution開始的,這個commit的SHA值為b21d5c1。

好的,讓我們動手,這個要使用git filter-branch的命令,基本上這是一個…破壞性有點高的指令,建議是把manpage好好讀過一遍之後再來使用,不然GG了我不負責。
Filter-branch可以傳入一個filter,然後基於這個filter上,把所有的commit重寫一篇
這裡要用的是--index-filter或--tree-filter,這個會改變commit的內容,另外還有像--env-filter改寫每個commit的環境設定,msg-filter用來改寫commit message等等。

每一個filter後面要接一個command,用來操作你的git倉庫,拿最簡單的來說,msg-filter會把目前的commit message送到你的command的stdin,然後以command stdout的內容當作新的commit message,例如我有一個倉庫依序加入abc三個檔案,現在長這樣:
b0b79d5 add c
f09a9d6 add b
2eee4d4 add a
如果我下:git filter-branch --msg-filter 'echo XDD' -- master
結果就會變成這樣:
075cdd6 XDD
44fe70f XDD
ec1e435 XDD
所有的commit message都被改寫成XDD,這簡直比改歷史教科書還要簡單

現在我們要移除掉dist資料夾,就使用--index-filter
git filter-branch --index-filter 'git rm -r --cached dist' -- b21d5c1^..
最後這個-- b21d5c1^..,是送到git rev-list的內容
git rev-list會把從某個branch往前回溯(嚴格來說是reachable)的每個branch寫出來,然後可以加上各種條件對這個群集進行操作,這裡我用例子來說明:
git rev-list master //master往前的所有commit
git rev-list master ^branch //master 往前,但不是branch往前的commit
git rev-list branch..master //與上一行等價
另外還有...的用法,只是那個我還沒搞懂,搞懂了再另外寫一篇XDD
前面提到,windows的東西第一次是出現在 b21d5c1這個commit
因此我們做的,就是從master往前所有commit裡面,把 b21d5c1前一個commit再往前的排除掉,因此只會更改到 b21d5c1這個commit之後的東西,不然filter-branch就會重寫這個歷史,會花比較多的時間(這個垃圾project算了,請想像你有幾千個commit要修正的話?)。
指令是移除掉dist下的東西,就是個rm。

output大概會像這樣:
Rewrite b21d5c1abbaf39e02b817b0ccb7efdc54dbf6090 (1/14)rm 'dist/ADSToOrigin_win.exe'
rm 'dist/_hashlib.pyd'
rm 'dist/bz2.pyd'
rm 'dist/library.zip'
rm 'dist/python27.dll'
rm 'dist/select.pyd'
rm 'dist/unicodedata.pyd'
rm 'dist/w9xpopen.exe'

以下類似的東西重複14次,無非就是刪掉exe, pyd 巴啦巴啦,可以看見我到底存了多少exe垃圾在我的project裡面lol。

另外,我有些commit是針對windows distribution去commit的,這個指令一下這個commit就變成empty commits,因此我們再來:
git filter-branch --prune-empty -- b21d5c1^.. 註:這裡的SHA應該要換掉,只是我忘了是多少了。
這個參數可以在上面就下,一次做完比較痛快,這時候像windows distribution這個commit就不見了。

這樣我們已經讓記錄中不再記錄這個檔案,最後把它從.git裡面記錄刪掉,因為git reflog跟branch-filter本身都有對它的引用(你看看從git裡面刪東西是有多機車……)。
rm -Rf .git/refs/original //刪除branch-filter的引用
rm -Rf .git/logs/ //刪除reflog
git gc

最後,強制把你修改的分枝樹,把遠端的東西蓋掉。
git push origin master -f

這樣應該就差不多了,雖然說我弄完之後好像沒變小很多,不過我不是很清楚問題在哪...

參考資料:

1. Git 內部原理 - 維護及資料復原
2. ignoring doesn't remove a file

2014年6月25日 星期三

用word寫論文的一些技巧

站長最近都在忙論文,blog就這樣荒廢了,不過今天心血來潮,把幾個寫論文時用word+mathtype寫的技巧整理一下,分享給大家。
不過先聲明,個人還是認為用LaTeX寫才是真高手,只是站長小孬孬就用word寫,不像強者我同學們都用LaTeX。

其實我覺得大部分的技巧,我在前面三篇office中都整理的差不多了,主要就是:
第一:設定好階層
第二:使用樣式庫
第三:弄懂段落
第四:管理好參考資料
詳細請參考:
http://yodalee.blogspot.tw/2013/04/office-word1.html
http://yodalee.blogspot.tw/2013/05/office-word2.html
http://yodalee.blogspot.tw/2013/07/office-word3.html

文章到這邊就可以結束了當然,我還是把大略的流程整理一下,看情況隨機插入一些技巧:

1. 設定樣式庫:
一開始就先把大部分的樣式設好,這樣以後比較方便,我遇到大部分要設定的樣式總計為:

內文,標題,標題1-4(論文能寫到更多層我也覺得滿厲害的),目錄1-4,圖片,表格系列包括標題列格式、表格內文、表格註記,圖片標號,表格標號,reference樣式。

一些細節的設定等等再談,這裡先把大略的字體、大小都設定好了。

2. 把文章的幾個標題都打好:
什麼大綱、Contents,chapter 1什麼的,套用好格式。
接著,因為遇到標題、標題一應該要開新頁,因此在這兩個格式的「分行與分頁設定」中,選擇「段落前分頁」,沒事別亂加分頁符號,那會讓文件變得難以排版。
這時候,基本的文章架構應該已經有了,頁數也變得至少十頁,雖然說內容都是空的

3. 建標號:
把該用的標號建好:兩個基本款應該是Fig 跟Table,在「參考資料」-「插入標號」裡新增它們。
建立時可以選擇「編號方式」,讓標號的數字會依照章節數字跳動。

4. 打文章:
好啦這才是最花時間的地方,但這沒啥技巧,全是硬功夫,再好的排版軟體要是沒內容排也排不出東西。

5. 插圖片:
個人會在文件旁建立一個fig資料夾,依章節把圖片分好,就算圖片還沒畫,也可以先複製隨便一張圖片放著,然後在插入的視窗中選擇「插入與連結」,之後只要改動插入的圖片,選擇圖片按F9即會自動更新了。
插入圖片之後,記得選取圖片該行,將樣式改為「圖片」樣式。

6. 插標號:
每插入一張圖片、表格後就用參考資料-插入標號,選用已建好的標籤
在內文的地方就選交互參照,選適當的標籤,插入參照類型的「段落編號(部分顯示)」
內文就會自動變成Fig. xx
插入新圖片後只要全選後按「更新功能變數」或F9,所有編號都會自動更新。
另外因為標號跟它的內容要在同一頁,因此在「圖片」樣式的落段「分行與分頁設定」中,選擇「與下段同樣」,表格標號也如此設定,這樣表格、圖片和它的標號才會在同一頁。

7. 表格:
其實表格在2007後也有自己的樣式,不過我是覺得沒什麼設定的必要。
不過表格是有不少需要設定的內容:
* 在左上方M$的符號-「 word選項」-「進階」最後的「版面配置選項」,把「不要將跨頁的換行表格切斷」選起來,這樣一般大小的表格才不會在表格中間換頁,而是直接跳下一頁。
註:藏這麼深誰找得到啦!( ̄▽ ̄)╭∩╮
* 如果有一個非常長的表格(依我的論文22列以上大概都會超出一頁),那麼請把整個表格選起來,在「表格內容」-「列」-「允許列跨越頁分隔線」取消掉,才不會出現一列的內容被分到兩頁去。
* 同時把「跨頁標題重複」勾起來,讓word自動重複標題。
* 在「表格內容」的「表格」,設定為「文繞圖」,然後在「位置」中設定下方的邊界值,這樣表格後的文字才不會離表格太近。

8. 方程式:
好了我們說到word最WTF的地方了,基本上作者試了很多方式之後,還是無法自動的產生靠右的方程式編號,最後還是靠MathType來解決,反正word爛也不是一天兩天的事,同學說 LaTeX is the ultimate solution 或許真有幾分道理。

補:後來強者我同學為中大神在FB上面嗆我說,用word也是能正常為方程式編號的,方法如影片所示:
https://www.youtube.com/watch?v=JcB4nQ2AYts
我是還沒試過啦,不過既然是為中大神開示,應該就是正確無誤了。

9. 插目錄:
差不多有點內容就可以插入目錄了,在該插入的地方選「參考資料」-「目錄」,要圖表目錄還是一般目錄就自己選。
視狀況調整目錄1-4的樣式,只有一個靠右的定位點是必要的,如果發生目錄文字太長讓頁碼沒有靠右,請設定該樣式段落的「縮排」為「第一排」並設定適當縮排值。

10. 檢視技巧:
在上方的檢視裡:
* 選用Web 版面配置,可以盡情放大文件,橫軸的捲軸會消失,文件的內文會自動換行,這在寫太久眼睛很累的時候很好用
* 打開文件引導模式:左邊會有標題列的列表,點一下可以直接跳過去。
* 開新視窗:同一份文件開一個新的視窗,我的習慣是多開一個,一個用來打內文,另一份停在Reference的地方,要reference什麼Alt+Tab切到另一個視窗去找,就不需要用滑鼠一直滾來滾去。

結論:這篇文章只是出來騙文章數的。

2014年5月20日 星期二

回應整理:「google為何輸給Oracle:判決書小整理」

這篇是有關上一篇Google vs Oracle的判決書的回應,因為有些朋友看完那篇後,覺得筆者寫得太爛不夠清楚,提了一些意見,我就把回應跟上一篇的回應一齊整理在這裡,大家可以…呃…參考參考:

首先先來回應強者我同學Bonoshi對中文整理意見:


>>>其實我不大能接受這個作者的論述但自己又還提不出有力的反駁,他很顯然是在為專利和法律這兩個既存的實體辯護,然後藉著說外國媒體全都錯了表現自己相當冷靜客觀,因為一切只不過都按照規則來……所以這個作者對法律本身沒有什麼反省,然後一會兒拿菜單一會兒又拿文學這些和程式設計不能相比的東西去比喻為自己的立場辯護,讓我覺得非常可疑

答案是:是的,因為這是判決書;事實上圖書館與文學的例子都是判決所提,圖書館的例子是地方法院所採用的比喻。
在新觀念出現的時候,法律可能會套用舊觀念來推衍新觀念適用的法條;著作權本來是要保護作者創作的事物而生的權利,無疑今天我拿筆寫下的文章無疑是有著作權的保護,那我用鍵盤打出來的文章是否類推?打出來的原始碼呢?
實務上被認定為有,軟體著作權是這樣一步一步推上來的,我相信這個問題在法學界跟過去的訴訟一定有被討論過:這部分可能要看早一點的案子Computer Assocs. Int'l v.s Altai,裡面可能有討論。
當然不無網路和軟體改變法學認定的例子:例如我買了軟體,但我沒有取得所有權而是軟體授權,所以我是不能讓賣書一樣轉賣軟體;blog放mp3我的確沒有營利,但仍可能侵犯著作權。
法律之解釋可能隨新事物的出現而有所變化,Michael Crichton所著的危基當前,就是對於基因被申請為專利現象的反思;但軟體的著作權,目前是個已定論的概念,本案更進一步確認即使是API,譔寫人仍擁有著作權。

>>>關於「但Oracle在創作Java 時,並非只有有限種譔寫API的方式:Math.max 可以寫為Math.maximum。」
這並不成立,max和maximum都是歷史悠久的單字,後者至少18世紀出現,前者19世紀。如果API必須以有意義的單詞(自然語言、高階語言)作為組合,那就是有限種,而且種類相當的少,不能和旋律、音符或文學作品相比。再加上程序編程又有所謂coding style和convention,max(x, y)顯然比bigger(x, y)還被廣為接受,而且我相信這也不是Java的發明。

這裡應該是我舉例不足,實際上不止是這樣。
因為命名的選擇性跟編排有極大的彈性,為何是Java.lang.Math.max,而不是Java.Math.max?
Oracle方的證詞顯示這些Java library在譔寫時,是經過數年的討論與測試,選擇出最佳的命名方式和class間的依序方式,而google直接複製了這個編排過的命名(包括函式、物件、套件),也是本次討論中的重點。

>>>關於「google在android中逐字的複製37個API, 7000行程式碼」37個API指的是API的命名(xxx.yyy.zzz),我查到的資料說Java API有168個package,不過我去算新版的又更多。以比例來說,這樣還不算太糟不是嗎?如果有人說抄了一個API的命名就算抄,那接下來變數和函式的名稱是不是都要像公司商標和行號一樣有版權來保護了XD

我覺得這邊只能透過個案討論認定,抄了一個max也許會被認定為合理使用,但google被認定為抄了'套件、物件、函式'整體架構的所有命名,如果我寫了一本書,有人抄了1/5的內容,這樣嚴不嚴重?抄了全本呢?只抄一行呢?抄了全本但把內容做random shuffle呢?
著作權的「合理」認定本身就是模糊的,所以才會說是「整部著作權法裡最大的麻煩」,但這類有點比例原則的問題,最簡單的判斷方式就是台語「謀郎安內」。
要把變數跟函式名稱要變做保護標的,被抄後要被認定是不合理,幾乎就跟我寫一篇小說設定女主角為「一個高中女生叫沈珈儀」然後要賠九把刀一樣困難。

>>>然後我很好奇7000行代碼到底是怎麼分佈的,是連續的7000行全抄,還是散落在各處?還有Java那方的實做總共有幾行?什麼樣就一致,是整行當中扣掉空白和tab之後的字串一模一樣嗎?(我假設是這樣)我沒有看過code我不知道,但是我覺得如果所有的程式碼當中,零零總總加起來不過只有7000行一致,要是我是Google我可以看過Java的實做然後把所有的變數名稱全部換掉、順序盡量改得不一樣(想一下資結如果A作不出來,拿B的來交,就會作相同的事),或是有些地方讀懂之後改成自己的方法,總之code改得很髒(也搞不好改得超乾淨,人家是Google耶……),最後比對之後沒有半行一致,可是這樣有意義嗎?

就我對Java的了解,應該是散落在各個java file裡面,google複製了前面的import, class name, class function declaration這些。
google在實作上是自行實作,所以應該可以預期google換掉大部分的變數名稱,判決書中有不少口語證詞跟文件證詞的部分,這裡我沒有細看。
而當然,爭議是在宣告的部分。

目前法院對軟體著作權並沒有任何界線,但有一套認定的程序在多次判決中被採用:(至少是non-literal code):abstraction – filtration – comparison。
Abstraction: break down the allegedly infringed program into its constituent structural parts.
Filtration: sift out all non-protectable material.
Comparison: compares the remaining creative expression with the allegedly infringing program.
詳細的內容我就不清楚了,但literal code中,法院會專注在filtration step (Mitel, Inc. v.s Iqtel, Inc.)

>>>要認真抓,應該要分析每一行的敘述結構(比如說int a = max(b, c)和int d = max(e, f)等價)和整個函式的結構分析,但如果用了敘述結構和結構分析,那問題就變成一個程式如果不是演算法,他的執行步驟到底能不能被保護。還有敘述結構這種可以和自然語言的句型相比的東西,根本不能被保護。所以我很堅持,智慧財產權法必須重新檢討過,法院拿圖書館和菜單來有點落伍又避重就輕。

這個問題有點複雜,我留到下面跟戰神Milk大大的問題一起回覆。

>>7000行程式碼一致很顯然Google是可以避開的。它沒有避開,那麼很可能代表它寧可不要創造出開發者完全不熟悉、但卻可以完全避開法律問題的東西(我們可以想想如果是微軟,它又會怎麼作XD)。在信仰上,Google可能自始自終就相信最後自己不會因為這件事件產生嚴重的法律問題。

我認為:是。因為重新訓練使用者比抄襲合解難上太多。
至於google信仰上是不是真的無惡意的這麼做?我這裡就不臆測了,但有評論認為,google遲早會以同樣的API抄襲理由來阻止三星發佈Tizen 平台。

--

接著是戰神Milk大大的質疑:


>>>是不是所有開發 C library 或實做部份 std function 的都應該要付授權金給標準制定協會?
不是,語言並不是著作權的部分

>>>那麼一個 function 的API制定出來之後,是不是就可以 prevent 別人使用一樣的API,除非你付錢?
以本案的判決來看,是的,除非你的API只有一種制定方式(就實務上來看幾不可能),或是使用某語言所必須,此時你的API可能會因此喪失著作權。的確不諱言,是否可能出現一些垃圾開發者先寫出一些程式碼,鼓勵所有人儘量使用;接著抽回授權開始一個一個控告?
因此我認為,所有的軟體授權都應開始正視這次訴訟的結果,修改軟體授權不溯及既往,發展不可否認的時間戳記。
事實上也有人認為這次判決能遏止大公司抄襲小公司發展的API,不過我個人對這樣成效是存疑,反而可能造成未來自由軟體授權更難推展,而是偏向保留著作權授權的後果。

>>>Java在部份 syntax 上等也借鏡了c++ 的 syntax,倘若concept可以受著作權保護,這樣Oracle公司是否應該付費給 C++ 標準委員會或取得授權?

不是,concept在美國著作權法102(b)內有明定:
In no case does copyright protection for an original work of authorship extend to any idea, procedure, process, system, method of operation, concept, principle, or discovery, regardless of the form in which it is described, explained, illustrated, or embodied in such work.
概念是無法受著作權保護的,事實上這點Oracle也承認,任何人都可以使用Java的Package-Class-Method的架構,他們並不擁有架構的著作權,而是36個class,20 subclasses與362個methods的命名和編排著作權。

>>>追問:Java 對既有的 C/C++ syntax 做出 extend 是否會侵害到原本的 C/C++ 可能使用族群的數量?如果有就是侵權行為?

還是否,syntax不是著作權法的保障範圍,你拿另一個語言的syntax怎麼用都是你家的事。
以寫書的比喻來說:我看有人用英文這個syntax寫書大賣,所以我也用英文寫,那個人能告我嗎?

共同提問:

>>>軟體產業是否應該把 API 認定為著作,而法官的行為會對於軟體產業有什麼後果?

我認為這個問題相當複雜,我只好打混說一下。
此例中法官並沒有討論這個問題,他是基於現行著作權法對軟體程式碼(source code, object code)的保護下,對API作出類似的認定。
我認為這個問題軟體原始碼是否受著作權法時就會討論,相關判例見Johnson Controls, Inc. v. Phoenix Control Sys.
我必須說我認為著作權法這個概念本身沒什麼問題,今天我好不容易寫了一本書,別人真的可以全文複製,掛上它的名字然後再出版一次嗎?
但,軟體是一個如此詭異的東西,本質上是一個介在文學與數學的東西,一方面它透過數學的邏輯架構,用嚴謹的定義規範一系列的運算步驟;另一方面它又是人類和電腦溝通的簡化「語言」,能把人類思考的巧思融入其中。
http://zh.wikipedia.org/wiki/%E8%91%97%E4%BD%9C%E6%AC%8A
參考著作權的維基,因為思考本身是無法申請為著作權的,從而「演算法、數學方法、技術或機器的設計」無法申請為著作,對海龍公式申請著作權會是一件很奇怪的事情。
那表達這式數學公式的軟體原始碼呢?我們為何能對一個演算法的原始碼申請專利呢?如果有最佳的解題步驟,不是應該每個人都寫出同樣的演算程式碼?
但世界不是這麼簡單,程式又融入了每個人的思考、想法,所以寫程式還是被歸入著作權當中,因為除去基本的演算法,把程式一塊一塊堆砌起來,還是需要設計師的巧思與智慧。

「複雜不含糊,嚴謹不簡明」
軟體的專利和原始碼的著作權爭議,相信未來仍會繼續下去。

題外話:


相比這個案例,我會說禁止相容PRM的規定,跟著作權延長、工具生產者入罪的危害大得多。本案引用的相容性案例,甚至直接指認將自己的東西相容於先行者是可行的做法,我認為有這些判例在先,打造相容環境在判決中是被隱性保障的。
也因此我認為wine跟bumblebee這類利用反工程破解先行者的架構,再自行重權相容環境,法院基本上認為是合理,且無涉原著作權人的著作權行使。
註:google的確有試圖論述這點,但法院認定android是無法與java相容的。
但有了PRM跟工具生產者入罪的規定,現行的這個「判例見解」平衡會被打破,這部分我就不班門弄斧,相關資料請參考:
http://ckhung0.blogspot.tw/2012/02/sopa-acta-tpp.html

附記:

靠回應比判決書長是怎麼回事……拜託別逼我了T_T,我要寫論文惹,不過最後請大家跟我高呼一聲:「開源碼萬歲,甲骨文去死」(誤)

2014年5月16日 星期五

google為何輸給Oracle:判決書小整理

眾所矚目的Google vs Oracle在前幾日判決,Oracle逆轉勝了這一局,因為我覺得此案實在太過重要,所以筆者就下載了判決書全文讀了一遍:
http://cdn1.vox-cdn.com/assets/4431835/13-1021.Opinion.5-7-2014.1.pdf

以及早先一些整理:
http://yowureport.com/?p=11928
http://www.fosspatents.com/2014/01/api-copyrightability-to-be-confirmed.html

並整理重要的論點在此,雖然說有一堆專業用詞不知道怎麼翻,還請路過高手指教;本文歡迎任何人轉載,但請註明出處'http://yodalee.blogspot.tw/' 或 'yodalee生活筆記'
注意此文是判決書論點之整理,不代表yodalee之個人意見,yodalee的個人意見是'開源碼萬歲 甲骨文去死'(誤)。

--

判決書的開頭就先解釋了Java, android, 前次判決的相關狀況,這裡就不再次說明,相信會來到這個垃圾blog的人的科技背景應該都不錯其實是版主自己懶

我們就從法律上來看,首先要先確立幾個背景:
  • source code, object code 的確受copyright literal part 保護(不然你覺得copyleft是為何而起?)
  • Google 承認Java API 為original and creative,法院也接受這個論述,也就是Java API的確構成copyright存在的要件
  • google在android中逐字的複製37個API, 7000行程式碼
“google agrees that it uses the same names and declarations in Android”
google複製了例如java.lang.math.max(int x, int y)這類的宣告,但重新實作了底層的implementation code。
所以爭議點在於:Google所複製7000多行的API,究竟是否屬於著作權法保障的範疇?在此判決中認定API屬於保護範圍,並逐一駁回google的理由。

google用了幾個說法,試圖認定Oracle的著作權為無效或android為合理使用等。

1. API是否落入Merger doctrine?
Merger doctrine: idea, expression should be split
當某個概念(idea)只能用有限的表達方式表達,則概念與表達融合,該表達變為不保護。
例如:輪子是一個概念,你要做到'輪子'的東西必須是圓的(難道能做方的輪子嗎…),所以你不能將圓形的這個表達方式設為保護範圍,並限制其他人使用類似的表達。
此決定是決定於製造輪子的時候,而非有人被訴製造輪子的時候;假設今天方的輪子也是可以用的時候,製造輪子的那個人就擁有圓形表達的著作權。
類似的案例,Nitendo曾展示多種不同加密卡帶的方式,因而取得卡帶加密方式的著作權。

google主張java API的實作方式和Java的概念已結合,因此API無法計入著作權保護,而google自行譔寫真正受保護的implementation code,從而避開侵權問題。
但Oracle在創作Java 時(吃屎吧你,明明是Sun),並非只有有限種譔寫API的方式:Math.max 可以寫為Math.maximum,Android可以用不同method分類方式,不同的命名選擇、不同的譔寫方式而達到同樣的效果,無法證明表達和概念是合一,使merger doctrine無法成立。
唯一的例外是三個核心的java packages: java.lang, java.io, java.util,不過google對此沒有特別主張。

2. API為短句,無法保護:
這就如先前整理所說,短句之集合為保護之對象。

3. scene a faire doctrine: 原創中必要的要素或習慣之物品不可為copyright: 
If they re standard, stock, or common to a topic, or if they necessarily follow from a common theme or setting. Apple Compute, Inc. vs. Microsoft Corp.
比如要描述警察,你就描述警棍、配槍、制服、鎮暴水車,所以你不能對描述這些內容的文字主張copyright,要求別人描述警察時不能這樣描述。
Google主張:這37個API已經成為寫Java時不可拋棄的部分,因此37個API的copyright已消失。

法院說:scene a faire的概念並無法證明Oracle copyright消失,只能作為google侵權之防守;但google無法提出明確證據指出android使用這37個API是必要,這個論點在地方法院就被駁回。

4. interoperability:
google主張此舉是為了與Java相容。
但interoperability並不表示著作權之消失,這裡使用的判決是Sony Computer Entertainment, Inc. vs Connectix, Corp.跟一個類似的案例。
總之Connectix用反工程的方式,製作出能和Sony卡帶相容的遊戲機,被認定為合理使用,但不影響著作權的創造、原創本身;而Google也顯然不是使用反工程的方式,了解Java 如何運作,再自行譔寫相關的執行程式;更進一步說,android上的程式和Java也稱不上相容。

5. Fair Use:
這就是惡名昭彰的'合理使用',根據是107條:
for purposes such as criticism, comment, news reporting, teaching (including multiple copies for classroom use), scholarship, or research, is not an infringement of copyright.
例如我今天想要痛罵祭止兀是笨蛋,我用了他臉書上寫的文章,此時他不能主張著作權;這個部分需要個案討論,事實上fair use被稱為:
'The most troublesome in the whole law of copyright'

這裡法院駁回google的理由是:

android並非Java之'transformative',如上,我要用祭止兀的照片提出評論或新聞使用,就幾不能有任何更動,而必預全部引用,並用於其他用途;顯然android並不合這個標準;同時google並非non-commercial的使用引用來的Java API,在實務上只要有營利性的行為,幾乎都會使合理使用的論述效力大幅下降。

--

大概說到這裡,我知道這樣其實稱不上什麼整理,如果有人提出更多的問題,我會再整理判決書內的回應貼上來。
看完判決,我覺得Oracle是佔在上風處,不過很有趣的,近十年來科技業最重要的兩個案件:Apple vs Samsung,Google vs Oracle
贏家Apple 跟Oracle保護了他們最重要的產品,但是卻輸掉了市場
也許智財權與著作權在軟體的保護已經近乎無效,即使得到保護,卻不一定留得住顧客的心。

ps. 然後我剛剛看到TSMC 控告Samsung侵權案勝訴,嗯…………

2014年5月9日 星期五

以pull request參與github專案開發

本魯最近看到一個有趣的專案: qucs
http://qucs.sourceforge.net/
目的是要打造一個類似ADS, AWR一樣的開源電磁模擬軟體,基本上是個野心勃勃,不過實際上沒多少人參與的專案,老實說還真令人擔心,我覺得還沒到一般人可用的階段應該就會腰斬了吧lol
不過難得有個專案跟本科相關,就進去玩一下好了,看看bug report,爬爬程式碼還真的修掉幾個bugs

好啦都修掉了那就來送個Pull Request吧…這玩意要怎麼送來著?
這時就只好自力救濟,問問旁邊的AZ大神跟QCL大神,QCL大神還很給力的直接殺到我房間教我;另外自己查了一點資料:
http://stackoverflow.com/questions/14680711/how-to-do-a-github-pull-request

對github的pull request 整理如下。
註:我其實不是很確定這個步驟是不是完全正確,如果有錯請大神們不吝指正 m(_ _)m

Step 1: get project

首先先在github網頁上,喜歡的project上按fork,把它複製到你的github上。
接著用終端機clone你的github:
git clone git@github.com:username/project
這樣會生成一個本地的git repository,它的Origin remote 設在你的github上。
為了方便參與開發,建議連接上原project的github,才能隨時保持你跟project無時無刻處在同步狀態:
git remote add upstream git@github.com:mainuser/project
這樣你的本地git就會連上原始project的github

Step 2: Open branch

接著就來修改吧。

通常新手使用git都會在來個「master大蜈蚣法」,一個master一路往前衝;不過project一大的時候還是建議開branch,改用「master大開花法」,每個branch只做一點點feature,然後再merge/rebase回master裡,反正git 就是branch怎麼開都無所謂。
參與pull request的時候更是如此,通常這時候project已經相當大了;儘量讓project manager看到少量的檔案變化,而不是整個project的檔案都變過;每個branch取個簡單易懂的名字:bug編號,feature編號都是不錯的選擇。
git branch -b branchname
git checkout branchname
or
git checkout -b branchname

Step 3: Make modification

修修補補。

Step 4: Send pull request

pull request會比較原始的github(也就是upstream)的某個branch,跟你的github裡的某個branch,把相關的commit 列出來,讓管理人決定要不要把你的commit接到它的branch上。另外,如果你在master上面加點東西,然後原開發者接受pull request,也在他的master上面加一些東西,兩個master間就產生衝突,所以請務必確保你的master是乾淨的。
Git push -u origin branchname
在你的github上面產生一個遠端branch。
接著到對方的github,按pull request,比較對方的master branch跟自己剛產生的這個branch。
第一個pull request就送出啦。

同時,在對方表態之前,這個branch就不要再動了,如上所說,github會比較兩個branch的差異,所以如果送出pull request之後又有變化,這些內容只會算到一個pull request裡,而不是每個feature一個pull request出去。當然如果你被拒絕了,你也可以繼續在這個branch上做修改,改好了再pull request一次。

Step 5: Merge, clean up

等待對方merge你的branch,merge之後,github會自動問你這個feature的branch要不要刪掉。
或者也可以用
git push origin :branchname
來刪掉遠端的branch,另外要用
git fetch origin -p
讓本地端更新遠端刪除掉的branch 的資訊。

最後要保持你的project跟遠端是同步的:
git fetch upstream
git checkout master
git rebase upstream/master

完成的畫面大概會像這樣:

整體的流程就是:我在origin/master的地方fork對方的project,接著在本地產生branch bug147,修正bug,推到我的github(origin)上。
對方merge我的pull request,更新了他的github(upstream)的master,我再用rebase把我的master移到最新的狀態。
如果你是高手,一次修10個bugs之類的,這時可以用rebase把其他應該修改的branch rebase到現在的master上。

以上,祝大家pull request愉快,大家快點來開發各種open source project

致謝:

本文感謝AZ大神及QCL大神的指導。

2014年5月5日 星期一

我的核四見解

好啦我先說,我寫這篇文已經抱持著被戰爆的可能了,特別是我記得我FB一直都保持擁核的態度,然後有一次在一長串的討論之後,我朋友就發了個推文「擁戴科學的人,理應謙卑的面對質疑,不要把所有假設都以為是理所當然/我只是覺得擁核方的態度有點討厭」

嗯嗯啊啊O_O,我只能弱弱的OS「我尊重你,你尊重我」啦,畢竟對方是電力組博士,而且這個發文自己跳出來回好像有點自己跳出去被打臉怪怪的。

--

好的,那麼我們開始吧。
從科學面來看,我對核能是持樂觀態度的;對核四,我則認為需要評估。

首先是核能,一直被戰的高階核廢料問題,並不是沒有方法解決,做成MOX燃料或進發展中的反應爐反應到半衰期短的廢料即可;我說目前高階核廢最好的處理方式,就是目前溼式的處理方式,靜待更新的處理方式出現;或者等到阻礙處理的政治問題解決。

至於核四,我認為工程上的問題,終歸有工程的方式來解決。
http://www.taiwan-panorama.com/tw/show_issue.php?id=199658505076C.TXT&table=0&h1=6YCP6KaW6LKh57aT&h2=5YWs5YWx5bu66Kit
可以參考這篇文章,看看阿扁總統(我記得我看完這篇之後超佩服他的)如何整頓台北捷運,讓它恢復上線。

即便是蓋得亂七八糟的木柵線,還是有適當的方式;如果帽梁出現裂鏠,可以透過覆鋼板解決;對安全系統有疑問,可以不斷的進行測試;這一切都是風險與後果的評估。

以飛安來比喻的話,現在全球平均一天有80K航班在飛行,例如馬航事件的風險事實上是以百萬分之一的等級(甚至更小)在算的,因此我們假定搭飛機是很安全的。或許有人覺得拿飛安比核電,實在是打火機比手榴彈,我覺得只是風險層次不同,概念是一樣的,更高的風險,就要更高的安全規格。

從技術角度來說核四的安全風險是可以評估而最小化的,同時工程上也有檢測的方式,我認為這是我擁核甚至擁核四的論點。
圍阻體裡面出現保特瓶,可以打掉重建,只要檢測得到同樣工程強度。
你怕高鐵出軌,你可以先跑三個月試試;核四你怕它會爆炸,讓它先測試一年再用最低功率試轉三年呢?這樣餘熱發生危險的機率也小。

如果「假設」核電廠最終一定要爆炸,那我們現在就要把所有的核電廠停下來,任何技術的討論都沒有意義。就像如果我們認為飛機很危險,那現在就該停飛所有航班改搭客輪(你這樣說歲月號怎麼辦?)。

喔然後我知道我寫到這裡一定又要被罵了,先別急,我還沒說完。

上面這些內容有一個很重要的前提:信任。
我只談科技,但現實的工程能不能跟上設計?沒了這個,上面一切都是白講。
「陳椿亮將捷運局一切資料公開,並開放記者全程旁聽採訪,還要求同仁做百分之百的配合。陳椿亮心裡始終堅信,捷運是「真金不怕火煉」,希望大家有一個公平的對待,還捷運局一個肯定。」現在政府能做到這樣嗎?

從政府現實面來看,我認為核四已經無法運轉了。
http://www.ptt.cc/bbs/Gossiping/M.1399040614.A.79C.html

這一切都是信任問題,這個政府跟工程品質可信嗎?政府你拿什麼說服我工程品質可信,馬路嗎?你為什麼不去吃屎?現在政府做得最好的不就消波塊(誤)?
簡而言之,無論從生活經驗、新聞、流言蜚語,我們不相信政府的施工品質;何況還有一個常識上我們覺得工程品質(特別是馬路Orz)遠勝於我們的日本,儘管事實上日本對核安的要求在東日本大地震前是不及台灣的。
現實上我會支持反核團體持續對政府施壓,作更完善的安檢,把一切資料公開出來,讓全民去檢視、抉擇,每個人都有不同風險的接受線,也許我比別人低了一點,我對台灣的工程水準信心比較高,這沒什麼對或錯的問題。
但當核災的後果已經放到很大,已經到了風險必須小到幾乎達不到的境界,要通過進行商轉幾乎是不可能的事。

結語我會說:「陽光是最好的消毒劑」
核四問題怎麼解?球在政府手上,陽光照亮核四,核電才有希望。
偏偏台灣政府一直覺得嘴砲才是最好的消毒劑,結果口水裡一堆細菌,愈講愈髒。
或許這是我送給核四的訃聞?

--

好不容易打完,我要睡了。
是說我在打這篇之前,隱約覺得我寫過核四相關文章,一查之下果然有lol。
http://yodalee.blogspot.tw/2013/03/blog-post.html
這個現在拿出來是老調重彈,我也覺得最近大家已經不會再亂轉貼奇怪的嘴砲了,大概是這篇文有它的效用(自我感覺良好中)。

參考資料:
1. 全球航運:
http://www.fdsm.fudan.edu.cn/emba/secondclass/Show.aspx?ID=ada40770-2fee-43c2-83b5-beb907f6fd0c
好啦其實這個資料不算太重要,事實我們對一些事都有奇怪的連結:
例如最近實驗室的同學與學長們正在準備去美國旅遊參加conferencepaper(註:好好喔T_T),選飛機的時候,有像是華航、長榮、Delta(?)之類的選擇,學長一口就咬定不要華航,原因是華航曾有「四年大限」的都市傳說,還外加那霸空港的意外。
好但是最後一次四年大限已經是12年前的事,那霸空港意外證實是波音的問題,可是大家還是不搭華航(何況長榮好像還比華航貴),潛意識裡,華航的意外造成現在對華航飛安的不信任。
說福島爆了所以核四也會爆,某種程度跟這樣的連結差不多,直接無視兩個核電條件有多不同。

2014年4月24日 星期四

在Archlinux 上編譯qtiplot

最近因為寫論文的關係,要作不少數據模擬、量測的圖,一般實驗室都是用Origin來作圖,不過我不知道為啥,在虛擬機裡面用Origin都會GG,一堆功能一點就當;而且Origin又不開源,吃土去吧。
這類的東西有沒有開源的替代方案呢?當然有。
Qtiplot SciDavis
兩套的介面其實非常像,不過qtiplot的功能比較完整。

--

用一用之後,就會對qtiplot愈來愈不爽()
反正有一些些功能還是怪怪的,例如改了range之後整張圖要重畫。
不過這是開源軟體,不像Origin不爽就只能不爽,想了一下決定立馬加入這個專案,反正這個軟體可能還要用一陣子。

結果載了最新的0.9.8.9的原始碼下來,第一大難關:不能編譯,費了不少勁才解掉。
首先要先裝必要的套件:qt4, vtk, boost lib, qt-assistant-compat,老實說多到我都有點記不住了。

然後有不少修改要做,主要是參考:
這個AUR包括了編譯成功需要的修改,果然Archlinux開發者都好猛OAO
照著改完就能成功編譯惹。

--

當然編成功了還是要mur一下,完全無法理解幹嘛把project搞到這麼難編譯,我真的覺得一個project容易編譯與否會直接關乎有多少開發者想要參與,編譯成功才能進行修改的測試,這是開始改project的第一步。
當然說回來,這個project也有一到兩年沒動過,大概也脫離密集開發期了。
現在至少累積了400features在排隊,編譯遇到的問題在原網站(BerilOS)幾乎都沒答案,而是分散到Debian, Archlinux, LaunchPad的幾個大的bug report去了,這大概是一個project在末期自然的狀況吧。

Reference:
1. qtiplot:
2. SciDavis:
3. qtiplot develop webpage:

2014年4月14日 星期一

使用git squash 合併commit

小弟之前一直有個習慣,每次寫程式都要寫到結果正確了,才把該commit的commit;這樣造成的結果是,常常累積了數百行的差異才commit,要是中途不小心手滑了一下,辛苦就全化作流水了。

阿蹦大神曰:不用結果正確,編譯可過就commit
這樣…不是會跑出一堆亂七八槽的commit嗎?

這就要用到git squash功能了
比如說現在我隨便commit一些版本,log顯示為:
commit 7549a19b591f1c802addf9b2344be2f607beff42
Date: Mon Apr 14 16:05:38 2014 +0000

    more line num

commit a15d1dde304646d542dc9cb596afbcd900a609c7
Date: Mon Apr 14 16:05:22 2014 +0000

    line num

commit 265e09db81b1c6aff81a6bedcd3a0e2f22e55acc
Date: Mon Apr 14 16:04:49 2014 +0000

    initial commit

如果要合併line num, more line num兩個版本:
$ git rebase -i 265e09db81b1c6aff81a6bedcd3a0e2f22e55acc

然後編輯將
pick a15d1dd line num
pick 7549a19 more line num
要squash起來的commit編輯為squash, 或fixup,前者會保留squash的commit message,後者只用最新的commit message,先改成:
pick a15d1dd line num
squash 7549a19 more line num

再來它會要求你修改commit message,這就隨便你改,預設是把兩個訊息寫在一起。
commit 0a947a06fd258e07615fb236696b8f31f04f4043
Date: Mon Apr 14 16:05:22 2014 +0000
    line num
    more line num

commit 265e09db81b1c6aff81a6bedcd3a0e2f22e55acc
Date: Mon Apr 14 16:04:49 2014 +0000

    initial commit

以後就寫個段落就commit一下,等到功能都寫完了,再全部squash起來即可。
參考資料: man git rebase
致謝: 本文感謝傳說中的阿蹦大神指導

2014年3月17日 星期一

使用python struct實作Dex file parser

最近因為學校作業的關係,開始碰一些android的相關內容;有一個作業要我們寫一個程式去改android dex file的opCode,不過我實力不足,最後用smali/baksmali+shell來實作,一整個就不是熟練的程式人該作的事O_O。
不過,為了補一下實力不足,還是用python 寫了一個Dex file parser:

因為Dex file已經包成binary的形式,要去parse其中的內容,最方便的套件就是python struct了,在這裡以Dex為例,來介紹python struct的使用:

要使用python struct,首先要寫出format string,struct 會依照format string對資料進行處理。
基本的格式是“nX”,其中n為重複數字,X為格式化代碼,例如I代表unsigned int_32。 前面還有endian的符號,這部分請自行查閱參考資料。
有了format string就可以呼叫struct的function: pack, unpack,它們會照format string,把資料寫到binary或從binary讀成一個tuple。

 例如:我們可以看到dex 35的header為:
typedefstructDexHeader {
u1 magic[8]; /*includes version number */
u4 checksum; /*adler32 checksum */
u1 signature[kSHA1DigestLen]; /*SHA-1 hash */
u4 fileSize; /*length of entire file */
u4 headerSize; /*offset to start of next section */
u4 endianTag;
u4 linkSize;
u4 linkOff;
u4 mapOff;
u4 stringIdsSize;
u4 stringIdsOff;
u4 typeIdsSize;
u4 typeIdsOff;
u4 protoIdsSize;
u4 protoIdsOff;
u4 fieldIdsSize;
u4 fieldIdsOff;
u4 methodIdsSize;
u4 methodIdsOff;
u4 classDefsSize;
u4 classDefsOff;
u4 dataSize;
u4 dataOff;
}DexHeader;

對這個我們可以寫出v35 format string為:"8sI20s20I",就這麼簡單。 接著我們可以呼叫unpack來取得header的內容。
infile = self.open(“yay.dex”, “rb”)
header = struct.unpack(self.v35fmt, infile.read(struct.calcsize(self.v35fmt)))
比較麻煩的一點是,unpack的資料長度必須和format string會處理到的長度一樣,這裡struct提供了calcsize來處理這個問題,它會回傳format string代表的長度。
print(header) (b'dex\n035\x00', 3615126987, b'A\x89\xd9Y\xd8mm\xe4\xfe\x9d8\x0c\xc25\xbc\xcc\x9b\x86\xbd)', 912, 112, 305419896, 0, 0, 752, 16, 112, 8, 176, 4, 208, 1, 256, 5, 264, 1, 304, 576, 336)

可以看見資料已經寫入tuple中了,之後再進行轉出即可。

2014年2月23日 星期日

Minecraft plugin fastbuild 2

這篇接續上一篇 最近花了一點時間,把fastbuild plugin本來預定的功能寫完了。

至於為什麼會相隔這麼久(16天),因為作者平常都在打東方有很多事情要忙,加上Java實在不是作者熟悉的語言,以致進度緩慢。
這次主要寫的是break的部分,原始碼比place 的listener多了一倍,因為break還涉及手中工具的耐久度設定、是否要掉下東西等,功能更複雜。
廢話不多說,來看看怎麼設計。

Event Handler

首先我們要聲請監聽票的event是BlockBreakEvent,這個event會在block被破壞的時候呼叫。 這個event會包含資訊有:玩家,被破壞的方塊。
為了要做到fastbuild的功能,我另外監看了PlayerInteractEvent,可以從這個事件中取得,玩家是碰到方塊的哪一個面。
因為plugin只能做到event based,因此這個plugin還是有一點限制,我們不能讓使用者邊敲方塊,後面一整排的方塊都開始出現裂痕,只能處理BlockBreakEvent(方塊已經爆了),再把後面的方塊設成空氣。這樣會產生一個問題:如果使用者用鏟子爆了泥土,可是後面是石頭,這樣不就可以用鏟子當超強挖礦工具?
所以這裡我們限制會一起挖的,只能是同樣類型的block。
for (int i = 0; i < n-1; i++) {
  nextBlock = block.getRelative(face);
  //currently only deal with same type block
  if (nextBlock.getType() == originType) {
    Collection drops = getDrops(tool, nextBlock);
    nextBlock.setType(Material.AIR);
    if (!isCreative) {
      // drops
      createDrops(nextBlock, drops);
      // durability
      if(!reduceDurability(tool,player)) {
        break;
      }
    }
  } else {
    break;
  }

Durability:

這部分參考[2][3],透過ItemStack的setDurability()跟getDurability()去設值,要注意的是durability值愈高表示工具愈爛,並且可以用ItemStack.getType().getMaxDurability(),來確定工具壞了,以免工具只能挖一格,卻把20格都挖掉了。

Enchantment:

我們處理的enchantment有unbreaking跟silk touch,分別影響durability跟drop items。 minecraft裡物品的item max durability值是恆定的,unbreaking只是在增加durability時加上一個機率,有一定的機不扣durability,在這裡我們複製這個設定。 可以透過ItemStack.getEnchantmentLevel(Enchantment ench); 來取得enchantment的值,非0表示有enchantment。

drops:

這裡我們呼叫 block.getDrops(ItemStack) 來產生drop items內容,用這個的好處是,它會自動判斷工具的等級高低,像用木鎬挖鐵礦,這個事件就會回傳空的內容。不過它不會處理工具有Silk touch的狀況,因些有Silk touch的時候要自己把原本的方塊傳回去。
最後再利用World.dropItemNaturally(Location, ItemStack)產生drop items即可。

Demo:

這個是用gtk-recordMyDesktop錄的,聲音好像比畫面還要慢一點,我也不知道問題在哪lol。

原始碼:

本程式公開所有原始碼,遇到bugs歡迎修改後丟pull request https://github.com/lc85301/FastBuild

參考資料:

1. Bukkit API Overview,要寫plugin不看這個不行www
http://jd.bukkit.org/
2. Minecraft Wiki enchantment:
http://minecraft.gamepedia.com/Enchanting
3. Minecraft Wiki tools
http://minecraft.gamepedia.com/Tools

2014年2月8日 星期六

Minecraft plugin fastbuild

最近想要寫一個快速整地用跟建設用的minecraft bukkit plugin,畢竟在進行大建築物的建設時,常常要剷平一整個山丘,或者要鋪一整片地板,很費工夫而且很慢,按著shift後退加滑鼠右鍵也很累。
用worldedit的確可以達成同樣的目標,可是那又太容易了。這個fastbuild的目標,就是一個威力中等的plugin,不像worldedit這麼有破壞力,保留建築材料自己取得的挑戰,又比用鐵鏟跟專注狂點右鍵更快一些,可以把精力用在建築物的設計上。
總結來說,worldedit是要讓creative mode更creative mode;fastbuild則是要讓survival mode 更creative mode一點。
雖然已經有人寫過了類似的東西,在參考資料[1],但它是mod,也沒有繼續更新,大體上我的目標和它是一樣的。

本plugin的spec如下:

1. 使用某個鍵或指令,目前設定是setn int,讀入使用者打入的數字。
2. 之後破壞方塊和放置方塊時,可以一次破壞/放置該數字的方塊。
3.破壞/放置方塊時的方向,視破壞/放置方塊哪個面而定,破壞上面,就是向下破壞n格;放置上面,就是向上放置n格。
4. 破壞方塊時,該數字目前先定在64,輸入超過數字會自動設在64。
5. 破壞方塊時,若n格內有空氣方塊,則破壞會穿過該格空氣。
6. 破壞方塊時,工具也會進行n次耐久減損判定,所以工具也要帶夠。
7. 破壞方塊時,若用鏟子挖土,但n格內可能有岩石,這要視bukkit怎麼設計。
8. 放置方塊時,該數字同樣先定在64,或者是放置時該stack所持有的方塊數量。
9. 放置方塊時,若遇到其他方塊擋路,則只放到擋路方塊為止。
10. 若以向上跳後向下放置方塊,一次放3個以上的方塊,可能會有窒息的風險或無法放置,這裡不處理。
11. 不支援復原,蓋錯了就要自己打掉,拆錯了自己建回去,科科科。

實際設計: 

開發minecraft,想到java;提到java,想到Sun;說到Sun,想到eclipse(誤)。 主要參考minecraft bukkit server的文件[2],步驟很詳細沒遇上太多問題。
package name: io.github.yodalee.FastBuild

照tutorial 的步驟,創建FastBuild class,用FastBuildSetnCmd接受setn command,用hashedMap記錄每一個玩家目前設定的值。
Event Handler是主要要寫的地方,這裡就要參閱bukkit API的文件,我們這裡要處理的,大部分是在org.bukkit.event.block之下,像放置block的org.bukkit.event.block.BlockPlaceEvent,我們就是要處理這個事件。

@EventHandler
public void onPlace(BlockPlaceEvent event){
}
這樣就可以處理這個事件,看看要幹什麼。
例如BlockPlaceEvent這個class裡面有一個setCancelled的function,用來設定這個event要不要被bukkit處理,如果我們這樣寫
@EventHandler
public void onPlace(BlockPlaceEvent event){
 event.setCancelled(true);
}
那這個server就再也不能蓋東西了ww。 或者可以玩一點更勁爆的
@EventHandler
public void onPlace(BlockPlaceEvent event) {
  Player player = event.getPlayer();
  Block block = event.getBlockPlaced();
  if (block.getType() == Material.DIAMOND_BLOCK) {
    player.getWorld().strikeLightning(player.getLocation());
  } 
}
算是某種禁奢條款,只要放置鑽石方塊想炫富就會被雷劈XD。

回到正題,我們要做的,其實就是從這個place Event裡,取出玩家放置的位子、方位,然後用for loop 重複呼叫placeBlockEvent即可。 目前bukkit好像無法呼叫「在某地放置方塊」的function,因此先用setType來實作,直接取代方塊。
Player player = event.getPlayer();
Block block = event.getBlockPlaced();
Block againstBlock = event.getBlockAgainst();
BlockFace face = againstBlock.getFace(block);
Block nextBlock = null;
ItemStack stackInHand = event.getItemInHand();
int stackAmount = stackInHand.getAmount();
int n,i;

//get n
if (plugin.playerN.containsKey(player)) {
  n = plugin.playerN.get(player);
} else {
  n = 1;
}
n = Math.min(n, stackAmount);

stackInHand.setAmount(stackInHand.getAmount() -1);
//build
if (face != null) {
  for ( i = 0 ; i < n-1 ; i++) {
    nextBlock = block.getRelative(face);
    if (checkReplaceable(nextBlock)) {
      nextBlock.setType(stackInHand.getType());
      block = nextBlock;
    } else {
      break;
    }
  }
}

// reduce itemStack in hand
if (player.getGameMode() != GameMode.CREATIVE) {
  stackInHand.setAmount(stackInHand.getAmount() - n);
  player.setItemInHand(stackInHand);
}
Build大體上的實作就是這樣,其實不算太難。 Break的部分,因為牽扯到手中工具耐久的問題,也許下次再來寫=w=。

Demo:


原始碼:

本程式公開所有原始碼,歡迎修改後丟pull request,這樣我也不用想break方塊怎麼寫了()
https://github.com/lc85301/FastBuild

參考資料:

1. minecraft mod fastbuild
http://www.youtube.com/watch?v=yT5zaBC9O_U
2. bukkit Plugin Tutorial
http://wiki.bukkit.org/Portal:Developers
3. YAML definition
http://wiki.bukkit.org/Plugin_YAML
4. Bukkit API Overview,喔這妖受好用的
http://jd.bukkit.org/

2014年1月21日 星期二

有關實習

最近,有人跟我提到實習的事情。基本上我是謝絕了,我覺得實習這種事大意不得。
畢竟我不像強者我同學們,如呂帥等可以身兼實習、課業和研究,我平時要顧好課業就已經力不從心,再加上實習肯定是雪上加霜。

我就曾有慘痛的教訓,大學時代的實習經歷,就是一個活生生的例子:
大學參加過一次實習,實習工作的內容是寫一些些程式,需要介面設計要跟美工合作,要發佈程式則需要上報主管配合。
那時候沒給實習分配足夠的時間,一星期只能上工一天到兩天左右,老闆根本人太好,還允許我這樣做O_O。
下場其實滿慘的。

造成的結果是每次工作前,都要和主管先確定工作內容是否有變動,打開上次的工作需要時間回憶上次的進度;沒有在現場的討論和密集溝通,讓美工很難配上我的進度,在兩者間來回的時間又拖到整個設計的流程。
更慘的其實是,那時候公司還在進化中,程式的標準模版也一直在變化中;因為我的進度比其他人慢了不少,程式和公司標準對不上,一起執行專案的主管,逼得要在我的程式碼與更新標準程式碼間來回。
誠心回想,我認為我那時的實習,對那家公司其實是很大的干擾,他們給了我很大的自由度,我的產出卻不是很好,到現在都覺得有點對不起他們(yay)。

之後我就大略拒絕所有實習的機會,我相信,要在實習中有收獲,學習到公司的運作、標準,參與公司流程,投入相當時間是必要的;否則,低頻參與的實習,以我的經驗來說其實是在浪費個人,以及實習公司的時間資源。
當然這可能是我個人的經驗,畢竟大部分的人應該都沒有我這麼廢,不過,也許可以給一些人作為參考,要不要聽這個建議,還是請大家自己評估。

 註:那你寫這篇文幹嘛o_O

實作:minecraft 豬人農場

直接進正題,總之看了youtube的設計:
http://www.youtube.com/watch?v=sEqKe10H6jo
就決定也來蓋一個。

不過因為用venture mode很難抓ghast,就只好用裝trapdoor或sign的方式,讓豬人自己走下來;而豬人的出生頻率和傳送門block的數量正比,因此門自然是愈大愈好;和影片中的口字型設計相比,田字的設計可以讓傳送門/黑曜岩的比例更高,因此選用田字型的設計;高跟寬設定為3x3,這個高度為67格高,加上摔落距離20格高,差不多接近minecraft時間流動的極限,因此設定為田字型3x3的設計,有點像建一個魔術方塊的框。

第一步是採集所需要的黑曜岩,所需要的量為:
垂直:21*3*16=1008
水平:21*4*3*8=2016
總合:3024單位黑曜岩,正好有一枝efficient V+unbreaking III的鑽石鎬,就好好的利用它,一口氣挖掉一整個岩漿峽谷,結果如下圖,放一個木塊是本來岩漿池的高度,直接倒水後整塊挖掉,都要挖到基岩了:

其他資源用量:

  • gravel: 5552單位,反正gravel沒用處,就把我家的gravel全用在這,沒想到還不夠(我家只有3400多個),還跟兩位朋友調了不少貨。
  • stoneslab: 5446 單位,這個其實不用,只是我覺得在下面一直滴水很討厭,就全部用一層stoneslab+一層gravel。
  • Trapdoor: 2765 單位,雖然說用sign比起來比較省木頭,不過trapdoor蓋起來比較快,木頭也不是什麼珍貴材料,就用trapdoor了。
  • Cobblestone: 1092 單位,主要是摔落塔跟底座。
  • Stonebrick: 563單位,這個是蓋四根支持柱,不是跟原PO一樣這麼求物理合理性的話可以不理這項。
  • Netherbrick: 292單位,用在黑曜岩間的填充跟走路的部分,純粹色調比較像。
  • Ladder: 582單位。
  • Fence: 450單位,防凍架使用。
其他還有一些漏斗,repeater,比較器做分類器,南瓜燈等,就不列上來了。

接著附幾張工程照片:
雪人掉落部分,這地方設計跟影片內相同:

建設中,因為我沒放很多光源,到了晚上就會變相撲競技場,被打到場外的話就會……:
平面部分建設完成,可以看到有些地方會積雪,這也是開始建設後才發現:
因此加設防凍架,以防水結冰:
黑曜岩矩陣:
trapdoor鋪設完成:
點火:
放水,上述平面的坡度,除了最底層是八格寬外,上面四層都是七格寬,只要最上一個放水,整個廣場都會有水流(廣場大小:73x73):
測試一下,效果十分顯著,如果積了太多,可以用splash of healing,可以瞬殺一群。
最後是一張全景照:

謝謝大家收看。