2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
21 |
22 |
受到 2013/8/3 時 25 萬人上凱達格蘭大道這件事的激勵,讓我想到能否號召網友們,形成一個沒有實體領土,只有虛擬領土的「網路國家」呢?
23 |
透過這個國家,我們可以制定法律、提出政策、甚至發動資訊戰。
24 |
而且、這些網民仍然是某些實體國家(例如台灣)的國民,因此仍然具有該國的投票權,所以就可以透過「網路公投」決定政策後, 要求政黨或立委認養這些政策並簽下契約,以換取將這些網民的票投給他們的「交易」。
25 |
我認為這種方式或許能讓網民可以有效的影響政府,並且跨過「公投法門檻過高」的問題。
26 |
於是我發了以下的訊息在「程式人雜誌的討論區」以及自己的 facebook 上,並引發了一些討論:
27 |
28 | 問題:我想我又瘋了,今年初我辦了一本新的雜誌,現在居然想成立一個新的國家
29 |
32 |
33 |
我之所以會認為應該用「虛擬國家」的概念,而非採用像「海盜黨」這樣的「黨」的慨念,或許原因之一是「黨」這個中文字 其實隱含了非常糟糕的負面意義,但是在英文中的 Party 卻沒有這種意思。
34 |
還有一個原因是,我想法中的這種網路組織,其實更像是一個國家,因為這個組織可以擁有「人民、土地、政府、主權」這四種形成國家的要素,只不過其領土 乃是在網路上的虛擬領土,而非真實世界的領土而已,有興趣的讀者可以參考以下兩篇文章。
35 |
39 |
那麼、虛擬國家的憲法應該是什麼樣的呢?以下是一個我構思中的範例:
40 |
41 | 任何人都可以經由明文宣誓的方式,成為網路公民國 (以下簡稱本國) 的公民 (以下簡稱網民)。
42 | 網民除了本國之外,還可以自由參加任何組織或實體國家,本國並無任何禁止「雙重國籍」的規定。
43 | 網民有上網之自由,任何組礙或限制網民上網的行為,都違反本憲法之精神。
44 | 網民有集會結社之基本權利,任何損害此一權利的組織,都將視為本國之敵人,本國有封鎖該組織的權利。
45 | 網民的任何作品,只要不附加「著作權宣告」,就被預設視為「公共領域」之作品,任何網民都擁有合法修改、複製、散布之權利。
46 | 網民可以下載任何未被身分認證機制所保護的內容,而不被控以侵犯著作權之自由。 ....
47 |
48 |
這樣的法律其實意在保障網民們的自由,並且同時尊重創作者的權力,但是將著作權的預設值反轉過來,從 CopyRight 「版權所有」的 All Rights Reserved 轉化為「版權所無」的 No Rights Reserved 的情況,這讓網路自由可以得到法律基礎。
49 |
這種手法與 GNU 的 GPL 有些不同,GPL 是透過法律來挑戰法律,但「網路虛擬國家」則直接透過「建國」與「制憲」挑戰傳統的政治結構。
50 |
「虛擬國家」或許不會擁有土地,但是卻擁有「網路空間上的領土」,可以透過「封鎖」、「不提供資訊」與實體國家進行對抗,網民們 也有可能透過像「鍵盤戰」的方式,進行某種形式的「虛擬戰爭」。
51 |
更重要的是,「虛擬國家」沒有禁止「雙重國籍」的規定,網民們在實體世界的國家裏,還是有投票權的。因此、「虛擬國家」可以透過 「公投」制定政策,試圖影響某個實體國家的政策,讓這些國家的政治可以更好。
52 |
舉例而言,如果台灣的「網民」們聯合起來,形成一個「虛擬國家」,例如叫做「網路公民國」(簡稱網國),就可以先在網路上制定政策 並且透過「公投」表決,決定建議國民將選票投給「認養」這個政策的「立委」或「政黨」,然後告訴「國民黨」與「民進黨」這個遊戲規則, 用「虛擬國家」的政策影響甚至左右「實體國家」的政策。
53 |
於是、這個虛擬國家成了一個「國中之國」,而且可以發揮強大的政治影響力,這就是我對「虛擬國家」運作方式的初步想法。
54 |
後記:我們甚至連國歌都寫好了,直接採用悲慘世界的革命之歌,配上自己填的歌詞,有興趣的朋友可以點選下列網址。
55 |
58 |
不過可惜的是,由於這個理想尚未得到真實國家的認同,筆者怕因為將自己唱國歌的錄音上網而被告,所以現在這首國歌只能私下唱, 因為這首歌的商業權還在華納公司的手上啊!請參考下列文章。
59 |
62 |
這也正是我們為何在上述憲法中要加入那些 CopyLeft 版權條款的原因啊!
63 |
當然、您也可以直接宣誓加入這個虛擬國家,只要在 facebook 上按一下加入就行了。
64 |
67 |
【本文由陳鍾誠撰寫】
68 |
69 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/code/oc/jc1parser.js:
--------------------------------------------------------------------------------
1 | var fs = require("fs");
2 | require("./ccc");
3 |
4 | var tokens = [];
5 | var tokenIdx = 0;
6 |
7 | var scan=function(text) {
8 | var re = new RegExp(/(\/\*[\s\S]*?\*\/)|(\/\/[^\r\n])|(".*?")|(\d+(\.\d*)?)|([a-zA-Z]\w*)|([>== tokens.length)
40 | return false;
41 | var token = tokens[tokenIdx].token;
42 | if (o instanceof RegExp) {
43 | return token.match(o);
44 | } else {
45 | return (token == o);
46 | }
47 | }
48 |
49 | var isNextType=function(pattern) {
50 | var type = tokens[tokenIdx].type;
51 | return (("|"+pattern+"|").indexOf("|"+type+"|")>=0);
52 | }
53 |
54 | var compile=function(text) {
55 | printf("text=%s\n", text);
56 | scan(text);
57 | printf("tokens=%j\n", tokens);
58 | STMT_LIST();
59 | }
60 |
61 | // BLOCK = { STMT_LIST }
62 | var BLOCK=function() {
63 | next("{"); STMT_LIST(); next("}");
64 | }
65 |
66 | // STMT_LIST = {} | STMT {; STMT_LIST}?
67 | var STMT_LIST=function() {
68 | STMT();
69 | if (isNext(';')) { next(';'); STMT_LIST(); }
70 | }
71 |
72 | // STMT = FOR | WHILE | IF | return E | ASSIGN
73 | var STMT=function() {
74 | if (isNext("for")) {
75 | FOR();
76 | } else if (isNext("while")) {
77 | WHILE();
78 | } else if (isNext("if")) {
79 | IF();
80 | } else if (isNext("return")) {
81 | next("return");
82 | E();
83 | } else {
84 | ASSIGN();
85 | }
86 | }
87 |
88 | // FOR = for (STMT; E; STMT) BLOCK
89 | var FOR=function() {
90 | next("for"); next("("); STMT(); next(";"); E(); next(";"); STMT(); next(")"); BLOCK();
91 | }
92 |
93 | // WHILE = while (E) BLOCK
94 | var WHILE=function() {
95 | next("while"); next("("); E(); next(")"); BLOCK();
96 | }
97 |
98 | // IF = if (E) BLOCK (else if (E) BLOCK)* (else BLOCK)?
99 | var IF=function() {
100 | next("if"); next("("); E(); next(")"); BLOCK();
101 | while (isNext("else")) {
102 | next("else");
103 | if (isNext("if")) {
104 | next("if"); next("("); E(); next(")"); BLOCK();
105 | } else {
106 | BLOCK();
107 | }
108 | }
109 | }
110 |
111 | // ASSIGN = (ID[++|--]?)?(=E)?
112 | var ASSIGN=function() {
113 | var id="", op="";
114 | if (isNextType("id")) {
115 | id = next(null);
116 | if (isNext("++") || isNext("--"))
117 | op = next(null);
118 | }
119 | if (isNext("=")) {
120 | next("=");
121 | E();
122 | }
123 | }
124 |
125 | // E=T ([+|-|*|/|%|&|^|||&&||||>>|<<|==|<=|>=|<|>] T)?
126 | var E=function() {
127 | t1 = T();
128 | if (isNextType("op2")) {
129 | var op = next(null);
130 | T();
131 | }
132 | }
133 |
134 | // T=STRING | INTEGER | FLOAT | ( E ) | FUNCTION | ID (ARGS)?
135 | var T=function() {
136 | if (isNextType("string|integer|float")) {
137 | return next(null);
138 | } else if (isNext("(")) {
139 | next("("); E(); next(")");
140 | } else if (isNext("function")) {
141 | FUNCTION();
142 | } else if (isNextType("id")) {
143 | id=next(null);
144 | if (isNext("(")) { next("("); ARGS(); next(")"); }
145 | } else error();
146 | }
147 |
148 | // FUNCTION = function(ARGS) BLOCK
149 | var FUNCTION = function() {
150 | next("function"); next("("); ARGS(); next(")"); BLOCK();
151 | }
152 |
153 | var source = fs.readFileSync("test.j1", "utf8");
154 | compile(source);
155 |
--------------------------------------------------------------------------------
/htm/people1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
21 |
22 |
看到上述的人名,很多讀者勢必心中會產生一大堆問號?他們是誰?這些人之間有甚麼關連呢?
23 |
程式人雜誌曾經介紹過這四位當中的兩位,也就是 Stallman 與 Swartz,甚至也曾經談到過 Lessig , 但是還沒有介紹過 Assange,讓我們稍微介紹一下這些人的重要事蹟。
24 |
30 |
筆者之所以將這些人寫在一起,原因在於這些人是「鍵盤革命」這一個概念當中的重要人物,他們都利用「電腦、程式、網路」等工具,與當權者進行對抗。
31 |
Stallman 因為不滿程式碼被商業公司封閉起來,而創造了 GNU 組織與 GPL 這個開放原始碼的程式授權,以便強制商業公司開放原始碼。 Lessig 延續 Stallman 的想法,將開放原始碼的概念引入一般著作與網頁,創造出了 Creative Commons 授權。而 Swartz 則為了讓資訊的流通更容易, 創造出 Markdown 格式與 RSS 訂閱技術,並且因為想把學術論文開放而遭到起訴,最後更因此而自殺。
32 |
至於 Assange,則因為將那些政府機密大量上網,成為各國政府的頭號公敵,並因「性犯罪」的罪名而被瑞典通輯,因此後來向厄瓜多駐倫敦大使館尋求政治庇護,目前英國還企圖與「厄瓜多」談判將 Assange 引渡到瑞典受審當中。
33 |
以上這些人與事件,都涉及到「資訊揭露」的政治學,有些人用合法的方式企圖揭露資訊 (像是 Stallman, Lessig),而有些人則用目前法律不允許的手段去揭露資訊 (像是 Swartz 與 Assange)。
34 |
18 世紀工業革命 (第二波) 的結果,造成工業取代農業,因此政治上從封建莊園制度轉向了議會政治,權力的核心從封建領主轉向了資本家。
35 |
在今日 21 世紀的資訊革命 (第三波) 當中,權力又將如何移轉,這個世界會如何變化呢?
36 |
未來、網路與資訊科技會帶領我們建立怎麼樣的一個「政治結構」呢?這是筆者很想知道,但卻也還在探索當中的一個重要關注項目啊!
37 |
38 |
50 |
【本文由陳鍾誠取材並修改自維基百科,原本寫得很長,但是後來決定簡化,若您想看那個長的版本,我們也有留著,請點選 這裏 】
51 |
52 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/htm/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌。
18 |
19 |
43 |
說明:本期取材比較特殊,前半部分討論「網路與政治」這個與程式距離較遠的主題,不喜歡政治主題的讀者請直接從「程式人文集」開始閱讀,謝謝!
44 |
45 |
46 | 前言
47 |
51 | 程式人介紹
52 |
55 | 程式人短訊
56 |
61 | 程式人頻道
62 |
65 | 程式人討論區
66 |
69 | 程式人文集
70 |
78 | 雜誌訊息
79 |
80 |
81 |
程式人雜誌預定於每個月 1 日出刊,您可以從下列網址取得程式人雜誌的所有內容 (包含當月最新出刊的雜誌)。
82 |
85 |
86 |
竭誠歡迎程式人投稿,或者成為本雜誌的專欄作家,現在就可以加入 程式人雜誌社團 一同共襄盛舉。
87 |
本雜誌編輯為「陳鍾誠 (@ccckmit)」,若要聯絡編輯,請寄信到 ccckmit at gmail dot com 。
93 |
94 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/htm/netcountry.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
21 |
22 |
在苗栗大浦案激化之後,抗議的朋友們喊出了「今天拆大埔,明天拆政府」的口號,甚至還導致 政大教授徐世榮被在喊口號時當街被逮捕,後來更衍生出陳為廷、楊儒門、李建成等人也因潑漆事件而被逮捕的事件。
23 |
但是、筆者在此要討論的,不是這個事件,而是拆除政府的方法。
24 |
在過去尚未發展出民主制度的時代,拆政府的方法只有一種,那就是革命了,但是民主制度發展出來之後, 每到選舉時政府就會被拆掉然後重建。因此、民主制度可以說一種定期拆除政府的制度。
25 |
可惜的是,我們的民主政治似乎走到了一個困境,每次選舉都會拆掉政府,然後原地重建。但是新的政府往往沒有更好, 而且很可能更爛。
26 |
這次由「洪仲秋事件」,在台灣引發了「公民 1985」聯盟發起上凱達格蘭大道抗議的活動,展現了台灣網路世代的力量, 在盡可能排除政黨勢力介入的情況下,集結了 25 萬人上街頭,卻又非常有秩序,而且有組織的進行了一場完美的街頭運動。
27 |
這件事讓筆者深受啟發,我認為這件事代表了「網路世代」是可以形成政治力量的,但是我也擔心這股力量隨著「洪仲秋事件」 的落幕而消散,網路世代從此又成為政治的邊緣人。這個世界仍然繼續由傳統的藍綠政治勢力所主導,那是我不願看到的。
28 |
兩年前我也曾經因為某個突然的啟發,開始了一場小革命,用網路來對抗現有的教育體制,以下是這場小革命的一些相關資訊:
29 |
35 |
以及我最近模仿賈伯斯的演講,講述了有關自己親身經歷的三個有關網路社群的故事,這篇讀的人比較多,而且有被 inside 網站轉載。
36 |
41 |
後來這場革命逐漸退燒了,我決定回到正常的生活,做一些有意義的事情,於是在去年底我決定創辦了「程式人雜誌」, 也就是各位現在看到的這本雜誌。
42 |
但是在 2013/8/3 日 25 萬人上凱道的事情過後,我內心哪個被壓抑下來的熱情又重新燃燒起來了,這也讓我思考 了好幾個晚上,甚至輾轉難眠。
43 |
我認為根本的問題是,網路世代其實被上一代所創建的體制所壓抑了,8 月 3 日的集結代表的不僅僅是抗議一個人被軍方虐死的事件, 而更深層的反應了「網路世代」企圖掙脫上一代所創造的枷鎖,然後創造一個更美好的世界。
44 |
但是、這種枷鎖根深蒂固的透過政治體制綑綁了我們,我們又如何能掙脫出來呢?
45 |
突然間、我想到一個可能的辦法,那就是讓網民們建立一個「虛擬國家」,然後用這個虛擬國家的力量,來影響實體國家, 讓政治有機會變得更好。
46 |
例如、在網路上,智慧財產權是一個很大的問題,我們每天的資訊分享幾乎都在觸犯法律,但是透過制定「網路虛擬國家」的憲法, 我們有機會得到與實體世界法律相抗衡的力量,這個想法乃是直接延伸自「開放原始碼」的 GPL 授權而來的,甚至也受「創作共用」 (Creative Commons) 的影響很深。
47 |
於是我寫了一些「網路憲法」的不成熟草案,希望透過這樣的方式改變現實世界的智慧財產權困境,以下是幾項不成熟的條文想法:
48 |
49 | 任何人都可以經由明文宣誓的方式,成為網路公民國 (以下簡稱本國) 的公民 (以下簡稱網民)。
50 | 網民除了本國之外,還可以自由參加任何組織或實體國家,本國並無任何禁止「雙重國籍」的規定。
51 | 網民有上網之自由,任何組礙或限制網民上網的行為,都違反本憲法之精神。
52 | 網民有集會結社之基本權利,任何損害此一權利的組織,都將視為本國之敵人,本國有封鎖該組織的權利。
53 | 網民的任何作品,只要不附加「著作權宣告」,就被預設視為「公共領域」之作品,任何網民都擁有合法修改、複製、散布之權利。
54 | 網民可以下載任何未被身分認證機制所保護的內容,而不被控以侵犯著作權之自由。
55 |
56 |
這樣的法律其實意在保障網民們的自由,並且同時尊重創作者的權力,但是將著作權的預設值反轉過來,從 CopyRight 「版權所有」的 All Rights Reserved 轉化為「版權所無」的 No Rights Reserved 的情況,這讓網路自由可以得到法律基礎。
57 |
這種手法與 GNU 的 GPL 有些不同,GPL 是透過法律來挑戰法律,但「網路虛擬國家」則直接透過「建國」與「制憲」挑戰傳統的政治結構。
58 |
「虛擬國家」的概念,目前仍然沒有明確的定義,在我的想法中,「虛擬國家」不會只是一個網路社團而已,還會有「憲法、虛擬領土、主權」、 甚至也可以「宣戰,媾和」。
59 |
根據德國公學者耶林內克(G.Jellinek)的說法,國家的四個構成要素是「人民、土地、政府、主權」。
60 |
在這四項要素中,「虛擬國家」擁有人民,也就是網民,擁有「主權」,像是智慧財產權等等,也可以建立「政府」,雖然這個政府可能只 是個「網路平台基礎建設」,以及一些維持這個基礎建設正常運作的志工,就像是維基百科一樣,但是仍然是個「政府」,而且大部分的 政策都可以透過「直接投票」-- 或說是「公民投票」而決定。
61 |
「虛擬國家」或許不會擁有土地,但是卻擁有「網路空間上的領土」,可以透過「封鎖」、「不提供資訊」與實體國家進行對抗,網民們 也有可能透過像「鍵盤戰」的方式,進行某種形式的「虛擬戰爭」。
62 |
更重要的是,「虛擬國家」沒有禁止「雙重國籍」的規定,網民們在實體世界的國家裏,還是有投票權的。因此、「虛擬國家」可以透過 「公投」制定政策,試圖影響某個實體國家的政策,讓這些國家的政治可以更好。
63 |
舉例而言,如果台灣的「網民」們聯合起來,形成一個「虛擬國家」,例如叫做「網路公民國」(簡稱網國),就可以先在網路上制定政策 並且透過「公投」表決,決定建議國民將選票投給「認養」這個政策的「立委」或「政黨」,然後告訴「國民黨」與「民進黨」這個遊戲規則, 用「虛擬國家」的政策影響甚至左右「實體國家」的政策。
64 |
於是、這個虛擬國家成了一個「國中之國」,而且可以發揮強大的政治影響力,這就是我對「虛擬國家」運作方式的初步想法。
65 |
【本文由陳鍾誠撰寫】
66 |
67 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/htm/info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
26 |
27 |
28 |
程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌,如果您願意成為本雜誌的專欄作家,請加入 程式人雜誌社團 一同共襄盛舉。
29 |
我們透過發行這本雜誌,希望讓大家可以讀到想讀的書,學到想學的技術,同時也讓寫作的朋友的作品能產生良好價值 – 那就是讓讀者根據雜誌的價值捐款給慈善團體。 讀雜誌做公益也不需要有壓力,您不需要每讀一本就急著去捐款,您可以讀了十本再捐,或者使用固定的月捐款方式,當成是雜誌訂閱費,或者是季捐款、一年捐一次等都 OK ! 甚至是單純當個讀者我們也都很歡迎! 本雜誌每期參考價:NT 50 元,如果您喜歡本雜誌,請將書款捐贈公益團體。例如可捐贈給「羅慧夫顱顏基金會 彰化銀行(009) 帳號:5234-01-41778-800」。(若匯款要加註可用「程式人雜誌」五個字)
30 |
想訂閱本雜誌的讀者,請按 雜誌訂閱 連結並填寫表單,我們會在每一期雜誌出刊時寄送通知與下載網址到您的信箱。
31 |
32 |
給專欄寫作者: 做公益不需要有壓力。如果您願意撰寫專欄,您可以輕鬆的寫,如果當月的稿件出不來,我們會安排其他稿件上場。
33 |
給網誌捐贈者: 如果您沒時間寫專欄或投稿,沒關係,只要將您的網誌以 [創作共用的「姓名標示、非商業性、相同方式分享」授權] 並通知我們,我們會自動從中選取需要的文章進行編輯,放入適當的雜誌當中出刊。
34 |
給文章投稿者: 程式人雜誌非常歡迎您加入作者的行列,如果您想撰寫任何文章或投稿,請用 markdown 或 LibreOffice 編輯好您的稿件,並於每個月 25 日前投稿到程式人雜誌社團 的檔案區,我們會盡可能將稿件編入隔月1號出版程式人雜誌當中,也歡迎您到社團中與我們一同討論。
35 |
如果您要投稿給程式人雜誌,我們最希望的格式是採用 markdown 的格式撰寫,然後將所有檔按壓縮為 zip 上傳到社團檔案區給我們, 如您想學習 markdown 的撰寫出版方式,可以參考 [程式人雜誌的出版方法] 一文。
36 |
如果您無法採用 markdown 的方式撰寫,也可以直接給我們您的稿件,像是 MS. Word 的 doc 檔或 LibreOffice 的 odt 檔都可以,我們 會將這些稿件改寫為 markdown 之後編入雜誌當中。
37 |
38 |
您也可以擔任程式人雜誌的編輯,甚至創造一個全新的公益雜誌,我們誠摯的邀請您加入「開放公益出版」的行列,如果您想擔任編輯或創造新雜誌,也歡迎到 程式人雜誌社團 來與我們討論相關事宜。
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
52 |
53 |
54 |
55 | 財團法人羅慧夫顱顏基金會
56 | http://www.nncf.org/ lynn at nncf dot org 02-27190408分機 232
62 | 顱顏患者 (如唇顎裂、小耳症或其他罕見顱顏缺陷)
63 | 銀行:009彰化銀行民生分行 帳號:5234-01-41778-800
64 |
65 |
66 | 社團法人台灣省兒童少年成長協會
67 | http://www.cyga.org/ cyga99 at gmail dot com 04-23058005
73 | 單親、隔代教養.弱勢及一般家庭之兒童青少年
74 | 銀行:新光銀行 戶名:台灣省兒童少年成長協會 帳號:103-0912-10-000212-0
75 |
76 |
77 |
78 |
79 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/code/oc/jparser.js:
--------------------------------------------------------------------------------
1 | var fs = require("fs");
2 | require("./ccc");
3 |
4 | var tokens = [];
5 | var tokenIdx = 0;
6 |
7 | var scan=function(text) {
8 | var re = new RegExp(/(\/\*[\s\S]*?\*\/)|(\/\/[^\r\n])|(".*?")|(\d+(\.\d*)?)|([a-zA-Z]\w*)|([>== tokens.length)
40 | return false;
41 | var token = tokens[tokenIdx].token;
42 | if (o instanceof RegExp) {
43 | return token.match(o);
44 | } else {
45 | return (token == o);
46 | }
47 | }
48 |
49 | var isNextType=function(pattern) {
50 | var type = tokens[tokenIdx].type;
51 | return (("|"+pattern+"|").indexOf("|"+type+"|")>=0);
52 | }
53 |
54 | var compile=function(text) {
55 | printf("text=%s\n", text);
56 | scan(text);
57 | printf("tokens=%j\n", tokens);
58 | PROG();
59 | }
60 |
61 | // NTS = NT { sep NT }*
62 | var repeat=function(f, sep) {
63 | f();
64 | while (isNext(sep)) {
65 | next(sep);
66 | f();
67 | }
68 | }
69 |
70 | // PROG = STMTS
71 | var PROG=function() {
72 | repeat(STMT, ';');
73 | }
74 |
75 | // BLOCK = { STMTS }
76 | var BLOCK=function() {
77 | next("{");
78 | if (!isNext("}")) repeat(STMT, ";");
79 | next("}");
80 | }
81 |
82 | // STMT = FOR | WHILE | IF | return EXP | ASSIGN
83 | var STMT=function() {
84 | if (isNext("for")) {
85 | FOR();
86 | } else if (isNext("while")) {
87 | WHILE();
88 | } else if (isNext("if")) {
89 | IF();
90 | } else if (isNext("return")) {
91 | next("return");
92 | EXP();
93 | } else {
94 | ASSIGN();
95 | }
96 | }
97 |
98 | // FOR = for (STMT; EXP; STMT) BLOCK
99 | var FOR=function() {
100 | next("for"); next("("); STMT(); next(";"); EXP(); next(";"); STMT(); next(")"); BLOCK();
101 | }
102 |
103 | // WHILE = while (EXP) BLOCK
104 | var WHILE=function() {
105 | next("while"); next("("); EXP(); next(")"); BLOCK();
106 | }
107 |
108 | // IF = if (EXP) BLOCK (else if (EXP) BLOCK)* (else BLOCK)?
109 | var IF=function() {
110 | next("if"); next("("); EXP(); next(")"); BLOCK();
111 | while (isNext("else")) {
112 | next("else");
113 | if (isNext("if")) {
114 | next("if"); next("("); EXP(); next(")"); BLOCK();
115 | } else {
116 | BLOCK();
117 | }
118 | }
119 | }
120 |
121 | // ASSIGN = (ID[++|--]?)?(=EXP)?
122 | var ASSIGN=function() {
123 | var id="", op="";
124 | if (isNextType("id")) {
125 | id = next(null);
126 | if (isNext("++") || isNext("--"))
127 | op = next(null);
128 | }
129 | if (isNext("=")) {
130 | next("=");
131 | EXP();
132 | }
133 | }
134 |
135 | // EXP=TERM (op2 TERM)?
136 | var EXP=function() {
137 | t1 = TERM();
138 | if (isNextType("op2")) {
139 | var op = next(null);
140 | TERM();
141 | }
142 | }
143 |
144 | // TERM=STRING | INTEGER | FLOAT | FUNCTION | ARRAY | TABLE | ID (TERMS)? | ( EXP )
145 | var TERM=function() {
146 | if (isNextType("string|integer|float")) {
147 | return next(null);
148 | } else if (isNext("function")) {
149 | FUNCTION();
150 | } else if (isNext("[")) {
151 | ARRAY();
152 | } else if (isNext("{")) {
153 | TABLE();
154 | } else if (isNextType("id")) {
155 | id=next(null);
156 | } else if (isNext("(")) {
157 | next("("); EXP(); next(")");
158 | if (isNext("(")) { next("("); TERMS(); next(")"); }
159 | } else error();
160 | }
161 |
162 | // FUNCTION = function(IDS) BLOCK
163 | var FUNCTION = function() {
164 | next("function"); next("(");
165 | if (!isNext(")")) repeat(ID, ",");
166 | next(")"); BLOCK();
167 | }
168 |
169 | // ARRAY = [ TERMS ];
170 | var ARRAY = function() {
171 | next("[");
172 | if (!isNext("]")) repeat(TERM, ",");
173 | next("]");
174 | }
175 |
176 | // TABLE = { PAIRS }
177 | var TABLE = function() {
178 | next("{");
179 | if (!isNext("}")) repeat(PAIR, ",");
180 | next("}");
181 | }
182 |
183 | // PAIR = TERM:TERM
184 | var PAIR = function() {
185 | TERM(); next(":"); TERM();
186 | }
187 |
188 | var source = fs.readFileSync("test.j1", "utf8");
189 | compile(source);
190 | compile(fs.readFileSync("test2.j1", "utf8"));
--------------------------------------------------------------------------------
/code/oc/as0.js:
--------------------------------------------------------------------------------
1 | var c = require("./ccc"); // 引用基本函式庫 ccc.js
2 | var as = require("./as"); // 引用抽象組譯器物件 as.js
3 | var code = require("./code"); // 引用指令物件 code.js
4 | var cpu0 = require("./cpu0"); // 引用處理器物件 cpu0.js
5 |
6 | var as0 = new as(cpu0.opTable); // 建立 as0 組譯器物件
7 |
8 | as0.parse = function(line) { // 剖析組合語言指令,建立 code 物件
9 | return new code(line, this.opTable);
10 | }
11 |
12 | as0.translate = function(code) { // 指令的編碼函數
13 | var ra=0, rb=0, rc=0, cx=0;
14 | var pc = code.address + 4; // 提取後PC為位址+4
15 | var args = code.args, parseR = code.parseR; // 取得 code 物件的函數
16 | var labelCode = null; // JMP label 中 label 所對應行的物件,稱為 labelCode
17 | if (code.op == undefined) { // 如果沒有指令碼 (只有標記),則清空目的碼
18 | code.obj = "";
19 | return;
20 | }
21 | switch (code.op.type) { // 根據指令型態
22 | case 'J' : // 處理 J 型指令,編出目的碼 OP Ra+cx
23 | switch (code.op.name) {
24 | case "RET": case "IRET" : // 如果式返回或中斷返回,則只要輸出 op 碼
25 | break;
26 | case "SWI" : // 如果是軟體中斷指令,則只有 cx 參數有常數值
27 | cx = parseInt(args[0]);
28 | break;
29 | default : // 其他跳躍指令,例如 JMP label, JLE label 等
30 | labelCode = this.symTable[args[0]]; // 取得 label 符號位址
31 | cx = labelCode.address - pc; // 計算 cx 欄位
32 | break;
33 | }
34 | code.obj = c.hex(code.op.id,2)+c.hex(cx, 6); // 編出目的碼 OP Ra+cx
35 | break;
36 | case 'L' : // 處理 L 型指令,編出目的碼 OP Ra, Rb, cx
37 | ra = parseR(args[0]); // 取得 Ra 欄位
38 | switch (code.op.name) {
39 | case "LDI" : // 處理 LDI 指令
40 | cx = parseInt(args[1]); // 取得 cx 欄位
41 | break;
42 | default : // 處理 LD, ST, LDB, STB 指令
43 | if (args[1].match(/^[a-zA-Z]/)){ // 如果是 LD LABEL 這類情況
44 | labelCode = this.symTable[args[1]]; // 取得標記的 code 物件
45 | rb = 15; // R[15] is PC
46 | cx = labelCode.address - pc; // 計算標記與 PC 之間的差值
47 | } else { // 否則,若是像 LD Ra, Rb+100 這樣的指令
48 | rb = parseR(args[2]); // 取得 rb 欄位
49 | cx = parseInt(args[3]); // 取得 cx 欄位 (例如 100)
50 | }
51 | break;
52 | }
53 | code.obj = c.hex(code.op.id, 2)+c.hex(ra, 1)+c.hex(rb, 1)+c.hex(cx, 4); // 編出目的碼 OP Ra, Rb, cx
54 | break;
55 | case 'A' : // 處理 A 型指令,編出目的碼 OP Ra, Rb, Rc, cx
56 | ra = parseR(args[0]); // 取得 Ra 欄位
57 | switch (code.op.name) {
58 | case "LDR": case "LBR": case "STR": case "SBR": // 處理 LDR, LBR, STR, SBR 指令,例如 LDR Ra, Rb+Rc
59 | rb = parseR(args[1]); // 取得 Rb 欄位
60 | rc = parseR(args[2]); // 取得 Rc 欄位
61 | break;
62 | case "CMP": case "MOV" : // 處理 CMP 與 MOV 指令,CMP Ra, Rb; MOV Ra, Rb
63 | rb = parseR(args[1]); // 取得 Rb
64 | break;
65 | case "SHL": case "SHR": case "ADDI": // 處理 SHL, SHR, ADDI 指令,例如 SHL Ra, Rb, Cx
66 | rb = parseR(args[1]); // 取得 Rb 欄位
67 | cx = parseInt(args[2]); // 取得 cx 欄位 (例如 3)
68 | break;
69 | case "PUSH": case "POP": case "PUSHB": case "POPB" : // 處理 PUSH, POP, PUSHB, POPB
70 | break; // 例如 PUSH Ra, 只要處理 Ra 就好,A 型一進入就已經處理 Ra 了。
71 | default : // 其他情況,像是 ADD, SUB, MUL, DIV, AND, OR, XOR 等,例如 ADD Ra, Rb, Rc
72 | rb = parseR(args[1]); // 取得 Rb 欄位
73 | rc = parseR(args[2]); // 取得 Rc 欄位
74 | break;
75 | }
76 | code.obj = c.hex(code.op.id, 2)+c.hex(ra, 1)+c.hex(rb, 1)+c.hex(rc,1)+c.hex(cx, 3); // 編出目的碼 OP Ra, Rb, Rc, cx
77 | break;
78 | case 'D' : { // 我們將資料宣告 RESW, RESB, WORD, BYTE 也視為一種指令,其形態為 D
79 | var unitSize = 1; // 預設的型態為 BYTE,資料大小 = 1
80 | switch (code.op.name) {
81 | case "RESW": case "RESB": // 如果是 RESW 或 RESB,例如 a:RESB 2
82 | code.obj = c.dup('0', this.size(code)*2); // 1 個 byte 的空間要用兩個16進位的 00 去填充
83 | break; // 例如:a RESB 2 會編為 '0000'
84 | case "WORD": // 如果是 WORD ,佔 4 個 byte
85 | unitSize = 4;
86 | case "BYTE": { // 如果是 BYTE ,佔 1 個 byte
87 | code.obj = ""; // 一開始目的碼為空的
88 | for (var i in args) { // 對於每個參數,都要編為目的碼
89 | if (args[i].match(/^\".*?\"$/)) { // 該參數為字串,例如: "Hello!" 轉為 68656C6C6F21
90 | var str = args[i].substring(1, args[i].length-1); // 取得 "..." 中間的字串內容
91 | code.obj += c.str2hex(str); // 將字串內容 (例如 Hello!) 轉為 16 進位 (例如 68656C6C6F21)
92 | } else if (args[i].match(/^\d+$/)) { // 該參數為常數,例如 26
93 | code.obj += c.hex(parseInt(args[i]), unitSize*2); // 將常數轉為 16 進位目的碼 (例如 26 轉為 1A)
94 | } else { // 該參數為標記,將標記轉為記憶體位址,例如 msgptr: WORD msg 中的 msg 轉為位址 (例如:00000044)
95 | labelCode = this.symTable[args[i]]; // 取得符號表內的物件
96 | code.obj += c.hex(labelCode.address, unitSize*2); // 取得位址並轉為 16 進位,塞入目的碼中。
97 | }
98 | }
99 | break;
100 | } // case BYTE:
101 | } // switch
102 | break;
103 | } // case 'D'
104 | }
105 | }
106 |
107 | // 使用範例 node as0 sum.as0 sum.ob0
108 | // 其中 argv[2] 為組合語言檔, argv[3] 為目的檔
109 | as0.assemble(process.argv[2], process.argv[3]);
110 |
--------------------------------------------------------------------------------
/source/article1.md:
--------------------------------------------------------------------------------
1 | ## Arduino入門教學(9) – 在 2x16 LCD 上顯示 "Hello World" 訊息 (作者:Cooper Maa)
2 |
3 | ### 實驗目的
4 |
5 | 練習使用 HD44780 相容的文字型 LCD(Liquid crystal display),在 2x16 LCD 上顯示 "Hello World” 訊息。
6 |
7 | ### 2x16 LCD 簡介
8 |
9 | 
10 |
11 | HD44780 相容的 2x16 LCD 可以顯示兩行訊息,每行 16 個字元,它可以顯示英文字母、希臘字母、標點符號以及數學符號,除了顯示訊息外,它還有其它功能,包括訊息捲動(往左和往右捲動)、顯示游標和 LED背光等。
12 |
13 | 
14 |
15 | LCD 總共有 14 支接腳,如果內建背光的話是 16 支,這些腳位的功能整理於下表:
16 |
17 | 腳位編號 名稱 說明
18 | --------- ----------------------------------------- --------------------------------------------------------------------------
19 | 1 Vss 接地 (0V)
20 | 2 Vdd 電源 (+5V)
21 | 3 Vo 或稱 Vee 對比(0-5V), 可接一顆 1k 電阻,或利可變電阻調整適當的對比
22 | 4 RS Register Select: 1: D0 – D7 當作資料解釋 0: D0 – D7 當作指令解釋
23 | 5 R/W Read/Write mode: 1: 從 LCD 讀取資料 0: 寫資料到 LCD, 因為很少從 LCD 這端讀取資料,可將此腳位接地以節省 I/O 腳位。
24 | 6 E Enable
25 | 7 D0 Bit 0 LSB
26 | 8 D1 Bit 1
27 | 9 D2 Bit 2
28 | 10 D3 Bit 3
29 | 11 D4 Bit 4
30 | 12 D5 Bit 5
31 | 13 D6 Bit 6
32 | 14 D7 Bit 7 MSB
33 | 15 A+ 背光(串接 330R 電阻到電源)
34 | 16 K- 背光(GND)
35 |
36 | 日立 HD44780 相容的 LCD 有 4-bit 和 8-bit 兩種使用模式,使用 4-bit 模式主要的好處是節省 I/O 腳位,通訊的時候只會用到 4 個高位元 (D4-D7),D0-D3 這四支腳位可以不用接。每個送到 LCD 的資料會被分成兩次傳送 – 先送 4 個高位元,然後才送 4 個低位元。
37 |
38 | ### 材料
39 |
40 | * 麵包板 x 1
41 | * Arduino 主板 x 1
42 | * HD44780 相容 LCD x 1 (本文所用的為 14 pin 無背光 LCD)
43 | * 旋轉式可變電阻 x 1
44 | * 單心線 x N
45 |
46 | ### 接線
47 |
48 | * 將 LCD 的 RS, Enable, D4, D5, D6, D7 依序接到 12, 11, 5, 4, 3, 2 等腳位上
49 | * 將 LCD 的 Vss 及 R/W 接到 GND,Vdd 接到 +5V
50 | * 可變電阻中間腳位接到 LCD 的 Vo,剩下的兩支腳位,一支接到 5V,另外一支接到 GND (註:也可以不使用可變電阻,只要在 LCD 的 Vo 上串接一顆 1k ohm 電阻連到 GND 即可)
51 |
52 | 
53 |
54 | ### 電路圖
55 |
56 | 
57 |
58 | ### 程式碼
59 |
60 | 要在 LCD 上顯示訊息,會涉及初始化 LCD 、下指令以及傳送資料給 LCD 等工作,Arduino LiquidCrystal Library 已經把這些工作簡化了,所以你不需要知道這些低階的指令。底下的程式在 2x16 LCD 上第一行顯示 "hello, world!” 訊息,並在第二行不斷更新 Arduino 重開之後經過的秒數,使用的是 4-bit 模式(HelloWorld.pde):
61 |
62 | ```CPP
63 |
64 | /* Lab9 - 在 2x16 LCD 上顯示 "Hello World" 訊息
65 | The circuit:
66 | * LCD RS pin to digital pin 12
67 | * LCD Enable pin to digital pin 11
68 | * LCD D4 pin to digital pin 5
69 | * LCD D5 pin to digital pin 4
70 | * LCD D6 pin to digital pin 3
71 | * LCD D7 pin to digital pin 2
72 | * 10K Potentiometer:
73 | * ends to +5V and ground
74 | * wiper to LCD VO pin (pin 3)
75 |
76 | This example code is in the public domain.
77 | http://www.arduino.cc/en/Tutorial/LiquidCrystal
78 | */
79 |
80 | // 引用 LiquidCrystal Library
81 | #include
82 |
83 | // 建立 LiquidCrystal 的變數 lcd
84 | // LCD 接腳: rs, enable, d4, d5, d6, d7
85 | // 對應到 Arduino 接腳: 12, 11, 5, 4, 3, 2
86 | LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
87 |
88 | void setup() {
89 | // 設定 LCD 的行列數目 (2 x 16)
90 | lcd.begin(16, 2);
91 |
92 | // 列印 "Hello World" 訊息到 LCD 上
93 | lcd.print("hello, world!");
94 | }
95 |
96 | void loop() {
97 | // 將游標設到 column 0, line 1
98 | // (注意: line 1 是第二行(row),因為是從 0 開始數起):
99 | lcd.setCursor(0, 1);
100 |
101 | // 列印 Arduino 重開之後經過的秒數
102 | lcd.print(millis()/1000);
103 | }
104 | ```
105 |
106 | 如果訊息沒有顯示在螢幕上,或者是模糊朦朧的,首先應該做的事是檢查可變電阻以調整對比。
107 |
108 | 註:這支是 Arduino 內建的範例程式,點選 File > Examples > LiquidCrystal > HelloWorld 就可以找到。
109 |
110 | ### 範例照片/影片
111 |
112 | * Arduino 筆記 -- Lab9 在 2x16 LCD 上顯示 "Hello World" 訊息 --
113 |
114 | ### 動動腦
115 |
116 | 1. 接一顆光敏電阻或可變電阻,然後寫一支程式讀取光敏電阻或可變電阻的讀值,並將讀到的數值顯示在 LCD 上。
117 | 2. 寫一支 SerialLCD 程式,程式的邏輯是: 接受來自 Serial Port 的資料(從 PC 或筆電端送出),然後把資料顯示在 LCD 上。
118 | 3. 承上題,把 SerialLCD 變成一個網路型的 LCD,讓電腦透過網路就可以把資料丟到 LCD 上顯示。
119 |
120 | ### 延伸閱讀
121 |
122 | * [How to control a HD44780-based Character LCD](http://home.iae.nl/users/pouweha/lcd/lcd.shtml)
123 | * [ladyada – Wiring up a character LCD to Arduino](http://www.ladyada.net/learn/lcd/charlcd.html)
124 | * [LCD 101](http://www.spikenzielabs.com/SpikenzieLabs/LCD_How_To.html)
125 | * [Scroll](http://arduino.cc/en/Tutorial/LiquidCrystalScroll) : scroll text left and right.
126 | * [Autoscroll](http://arduino.cc/en/Tutorial/LiquidCrystalAutoscroll) : shift text right and left.
127 |
128 | 【本文作者為馬萬圳,原文網址為: ,由陳鍾誠編輯後納入本雜誌】
129 |
--------------------------------------------------------------------------------
/css/pmag.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, applet, object, iframe,
2 | p, blockquote, pre,
3 | a, abbr, acronym, address, big, cite, code,
4 | del, dfn, em, img, ins, kbd, q, s, samp,
5 | small, strike, strong, sub, sup, tt, var,
6 | b, u, i, center,
7 | dl, dt, dd,
8 | fieldset, form, label, legend,
9 | table, caption, tbody, tfoot, thead, tr, th, td,
10 | article, aside, canvas, details, embed,
11 | figure, figcaption, footer, header, hgroup,
12 | menu, nav, output, ruby, section, summary,
13 | time, mark, audio, video {
14 | margin: 0;
15 | padding: 0;
16 | border: 0;
17 | font: inherit;
18 | vertical-align: baseline;
19 | line-height:160%;
20 | font-family: 'Tahoma', 'Pmingliu';
21 | }
22 |
23 | #cover-image {
24 | width:100%;
25 | }
26 |
27 | div>ol.toc {
28 | list-style-type:disc;
29 | }
30 |
31 | ol.toc {
32 | list-style-type:circle;
33 | }
34 |
35 | blockquote {
36 | margin: 10px;
37 | padding-left: 10px;
38 | padding-right: 10px;
39 | padding-top: 1px;
40 | padding-bottom: 1px;
41 | border: 1px solid #373737;
42 | background-color: #efefef;
43 | }
44 |
45 | h1, h1 a { font-size: xx-large; color:#050505; text-align:center; margin:30px; font-weight: bold; font-family: 'Tahoma', 'DFKai-sb'; }
46 |
47 | h2, h2 a { font-size: x-large; color:#000033; margin-top:30px; margin-bottom:30px; font-weight: bold; font-family: 'Tahoma', 'DFKai-sb'; }
48 |
49 | h3, h3 a { font-size: large; color:#000066; font-weight: bold; font-family: 'Tahoma', 'DFKai-sb'; }
50 |
51 | h4, h4 a { font-size: medium; color:#4B0082; font-weight: bold; font-family: 'Tahoma', 'DFKai-sb'; }
52 |
53 | h5, h5 a { font-size: small ; color:#708090; font-weight: bold; font-family: 'Tahoma', 'DFKai-sb'; }
54 |
55 | h6, h6 a { font-size: x-small; color:#000080; }
56 |
57 | p {
58 | font-family: 'Tahoma', 'Pmingliu';
59 | margin: 10px 0 15px 0;
60 | font-size:100%;
61 | color:#353535;
62 | }
63 |
64 | li {
65 | font-size:100%;
66 | }
67 |
68 | footer p {
69 | color: #f2f2f2;
70 | }
71 |
72 | a {
73 | text-decoration: none;
74 | color: #007edf;
75 | text-shadow: none;
76 |
77 | transition: color 0.5s ease;
78 | transition: text-shadow 0.5s ease;
79 | -webkit-transition: color 0.5s ease;
80 | -webkit-transition: text-shadow 0.5s ease;
81 | -moz-transition: color 0.5s ease;
82 | -moz-transition: text-shadow 0.5s ease;
83 | -o-transition: color 0.5s ease;
84 | -o-transition: text-shadow 0.5s ease;
85 | -ms-transition: color 0.5s ease;
86 | -ms-transition: text-shadow 0.5s ease;
87 | }
88 |
89 | table {
90 | border-collapse: collapse;
91 | border-spacing: 0;
92 | border: 1px solid #373737;
93 | margin-bottom: 20px;
94 | text-align: left;
95 | margin-left:auto;
96 | margin-right:auto;
97 | }
98 |
99 | th {
100 | padding: 10px;
101 | background-color:black;
102 | color:white;
103 | }
104 |
105 | td {
106 | padding: 10px;
107 | vertical-align: middle;
108 | border: 1px solid #373737;
109 | }
110 |
111 | em {
112 | font-weight:bold;
113 | }
114 |
115 | #header_wrap {
116 | margin: 0;
117 | padding: 16px;
118 | border: 0;
119 | font: inherit;
120 | vertical-align: baseline;
121 | background-color:black;
122 | color:white;
123 | }
124 |
125 | #header_wrap h1, #header_wrap h1 sub, #header_wrap h1 a {
126 | color:white;
127 | font-family: 'Tahoma', 'DFKai-sb';
128 | }
129 |
130 | #header_wrap sub {
131 | color:white;
132 | font-size:60%;
133 | }
134 |
135 | .title, .author, .date {
136 | color:#333333;
137 | text-align:center;
138 | font-family: 'Tahoma', 'DFKai-sb';
139 | }
140 |
141 | .title { font-size:xx-large; line-height:800%; }
142 |
143 | .author { font-size:large; line-height:300%; }
144 |
145 | .date { font-size:large; line-height:300%; }
146 |
147 |
148 | #content {
149 | margin:10px;
150 | padding:10px;
151 | }
152 |
153 | pre {
154 | border: 1px solid #373737;
155 | background-color:#efefef;
156 | color:#3f3f3f;
157 | font-size:medium;
158 | width:95%;
159 | padding:10px;
160 | }
161 |
162 | code {
163 | font-family: SimSun;
164 | font-size:100%;
165 | }
166 |
167 | .figure {
168 | margin:10px;
169 | padding:10px;
170 | margin-left: auto;
171 | margin-right: auto;
172 | display: block;
173 | }
174 |
175 | .figure img {
176 | border: 1px solid #373737;
177 | margin-left: auto;
178 | margin-right: auto;
179 | display: block;
180 | }
181 |
182 | .figure .caption {
183 | text-align:center;
184 | }
185 |
186 | #TOC {
187 | }
188 |
189 | #footer {
190 | text-align:center;
191 | font-size:small;
192 | color:#6f6f6f;
193 | margin: 10px;
194 | padding: 10px;
195 | }
196 |
197 | /* JavaScript Style */
198 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
199 | margin: 0; padding: 0; vertical-align: baseline; border: none; }
200 | table.sourceCode { width: 100%; }
201 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #afafaf; border-right: 1px solid #aaaaaa; }
202 | td.sourceCode { padding-left: 5px; }
203 | code > span.kw { color: #007020; font-weight: bold; }
204 | code > span.dt { color: #902000; }
205 | code > span.dv { color: #40a070; }
206 | code > span.bn { color: #40a070; }
207 | code > span.fl { color: #40a070; }
208 | code > span.ch { color: #4070a0; }
209 | code > span.st { color: #4070a0; }
210 | code > span.co { color: #60a0b0; font-style: italic; }
211 | code > span.ot { color: #007020; }
212 | code > span.al { color: #ff0000; font-weight: bold; }
213 | code > span.fu { color: #06287e; }
214 | code > span.er { color: #ff0000; font-weight: bold; }
215 |
216 |
--------------------------------------------------------------------------------
/source/people1long.md:
--------------------------------------------------------------------------------
1 | ## 資訊政治人:Stallman, Lessig, Swartz 與 Assange
2 |
3 | 看到上述的人名,很多讀者勢必心中會產生一大堆問號?他們是誰?這些人之間有甚麼關連呢?
4 |
5 | 程式人雜誌曾經介紹過這四位當中的兩位,也就是 Stallman 與 Swartz,甚至也曾經談到過 Lessig ,
6 | 但是還沒有介紹過 Assange,讓我們稍微介紹一下這些人的重要事蹟。
7 |
8 | * Stallman : [開放原始碼之父–Richard Stallman], 是著名的程式人, GNU 組織的創建者,GPL 授權的制定者。
9 | * Lessig : [勞倫斯·雷席格], 哈佛大學憲法學教授,創作共用 (Creative Commons) 授權的創造者。
10 | * Swartz : [Markdown 與 RSS 的創造者-Aaron Swartz], 並且因從 MIT 校園內大量論文一案被起訴,然後不堪檢察官威脅而在 2013 年 1 月 11 日時自殺身亡。
11 | * Assange : 維基解密組織的創建者與核心人物。
12 |
13 | 筆者之所以將這些人寫在一起,原因在於這些人是「鍵盤革命」這一個概念當中的重要人物,他們都利用「電腦、程式、網路」等工具,與當權者進行對抗。
14 |
15 | Stallman 因為不滿程式碼被商業公司封閉起來,而創造了 GNU 組織與 GPL 這個開放原始碼的程式授權,以便強制商業公司開放原始碼。
16 | Lessig 延續 Stallman 的想法,將開放原始碼的概念引入一般著作與網頁,創造出了 Creative Commons 授權。而 Swartz 則為了讓資訊的流通更容易,
17 | 創造出 Markdown 格式與 RSS 訂閱技術,並且因為想把學術論文開放而遭到起訴,最後更因此而自殺。
18 |
19 | 至於 Assange,則因為將那些政府機密大量上網,成為各國政府的頭號公敵,並因「性犯罪」的罪名而被瑞典以通輯,因此後來向厄瓜多駐倫敦大使館尋求政治庇護,目前英國還企圖與「厄瓜多」談判將 Assange 引渡到瑞典受審當中。
20 |
21 | 以上這些人與事件,都涉及到「資訊揭露」的政治學,有些人用合法的方式企圖揭露資訊 (像是 Stallman, Lessig),而有些人則用目前法律不允許的手段去揭露資訊 (像是 Swartz 與 Assange)。
22 |
23 | 如果從「大歷史」的長遠角度來看,參考 [第三波 (The Third Wave)] 中 Alvin Toffler 對歷史的區分方法,人類歷史可以用「農業文明 => 工業文明 => 資訊文明」的方式簡化的描述,那麼我們現在正處於「資訊文明」的改變過程當中,以下是這三個時期的特徵列表。
24 |
25 | (第一波) 農業文明:17 世紀之前,土地、獸力、耕種社會、家族型態,…
26 | (第二波) 工業文明:1600-1950,工廠、銀行、技術、蒸氣機、引擎、資本主義,商業社會,重商主義,…
27 | (第三波) 資訊文明:1950-現今,電腦、網路、電子、資訊、媒體、全球化、…
28 |
29 | 在工業文明的前期,引發了「工業革命」這一浪潮,這個浪潮從「地理大發現」時期開始醞釀,到了「英國工業革命」時正式成形,並且也導致了後來的法國大革命與英國殖民主義的擴張,形成了「日不落帝國」,並讓「英語」成為了世界性通用的語言。
30 |
31 | 工業文明造成整個世界結構的改變,為了使得工廠的生產得以順利進行,讓得「大量生產、大量消費」的體制能夠順利運作、啟動了工業革命,結果造成「生產集中化、產品標準化、工作專門化、生產同步化、規模極大化、管理集權化」等工業文明的特性。
32 |
33 | ### 第二波:工業文明
34 |
35 | 第二波的社會結構以工廠為核心,所有組織都仿照工廠的形式,由於青壯年到工廠工作,兒童就進入學校,老人進入養老院。為了配合就業上的機動性,家庭結構因而解體為小家庭。
36 |
37 | 第二波的昂貴設備必須有較大的市場使生產貨物予以攤銷,但是如果一踏出自己的區域,就遇上不同的關稅、義務、勞工規定與貨幣,則規模化將無法達成。於是,歐洲中古世紀的莊園結構被取代,規模較大,統一性較高的現代國家於是形成。
38 |
39 | 工業文明利用機械力讓生產規模極大化,仰賴分工的原則,工作專門化的結果導致了生產者與消費者分離的現象 (產銷分離)。於是家庭自己自足的情況不復存在,這也造成了許多社會問題,像是家庭的解體、金錢至上、物欲橫流、功利主義等等。
40 |
41 | 產銷分離導致了市場交換網路的巨幅成長,利用大量生產、大量運送、大量消費的方式,讓工廠的產品得以送達全國,廉價的能源與燃料是這種輸送系統得以運行的重要原因。
42 |
43 | 產銷分離的結果也讓青少年無法與生產接軌,導致更多的青少年問題。兒童養育成本變得更高,於是少子化的狀況出現。家庭變得更不穩定,於是許多兒童與老人無人照料,仰賴社會救助的情況相當普遍。
44 |
45 | 極細緻的分工結果導致了專門化的社會,這樣的社會仰賴綜合者進行統合,於是全力集中在綜合者的身上,這些綜合者也就是公司的經理人、幕僚等等。
46 |
47 | 第二波社會的綜合管理方式大致上分為資本主義社會與共產主義社會,共產主義社會以強制的方式進行綜合,但資本主義社會則利用市場機制進行綜合,結果是資本主義社會較為有效,這也導致了後來的共產社會解體,紛紛向資本主義社會前進。
48 |
49 | 第二波的精神體系以機械論的科學體系為主,注重因果關係、可預測性、合理化,採用線性的時空觀念,輕視不可量化的東西,讚美規律,並懲罰想像力。
50 |
51 | 經濟理論上以市場機制為核心,亞當斯密國富論中的看不見的手、分工的好處與李嘉圖的國際分工論都傾向於強化交換網路。
52 |
53 | ### 第三波:資訊文明
54 |
55 | 技術上使用光電資訊,並以電腦為工具,最重要的資源為數位資訊,採用網路傳輸的通訊方式,社會結構分化成多元組織,家庭結構則變得多樣而多變。
56 |
57 | 艾文、托佛勒對第一波、第二波、第三波的描述令人激賞,他就像一個外星人來到地球上一般,一眼看出地球的社會組織架構與其他星球的差別。
58 |
59 | 托佛勒關於第一波、第二波的描述至今仍深受我認同,並成功的指出了第三波的資訊文明的到來,以及電腦網路所造成的巨大影響。
60 |
61 | 然而,以 1980 年代的視野,畢竟難以想像 40 年後的今天,資訊文明發展到何種程度,也難以預料到全球資訊網 Web 的發展途徑。如今,Web 已經發展了將近 20 年,我們得以看清一些當年托佛勒所無法看清的事實,也因此能站在托佛勒的肩牓上,進一步的思考資訊文明的過去、現在與未來。
62 |
63 | 資訊文明與工業文明最大的不同點,在於數位內容的生產領域,也就是文字、影像、音樂、程式等產品,這些產品不需送到工廠製造,只要透過網路即可進行銷售。
64 |
65 | 數位內容的主要成本為人事成本,一但建構完成,其複制成本幾近為零,因此銷授範圍變得更大。又因為使用者對軟體程式等領域具有學習門檻等問題,於是讓銷售市場更加統一 (梅特卡夫定律),微軟的 DOS, Windows 等軟體就是此類現像的典型證明。
66 |
67 | 托佛勒於第三波一書中,認為第三波會導致社會中產銷合一情況的增強,但這並不是我們今天所看到的樣子。
68 |
69 | 托佛勒認為所強調的『生產者-消費者』之分離現象區隔無法反映今日情況的奧妙之處,因此,筆者從電子商務領域借用 B (Business:商務) 與 C (Customer:客戶) 等兩個概念,取代『生產者-消費者』的分類法,以說明今日的情況。
70 |
71 | 電子商務將網路市場區分為 B2B, B2C, C2C 等 3 類,如此更能反映網路市場的演變情況,傳統商務著重在 B2B 與 B2C 這兩塊,但在網路中 C2C 的市場不斷的被突顯出來,而且快速的成長。但是這個市場並非托佛勒於第三波一書所說的產銷合一之市場,因為兩個 C 所代表的是兩個客戶端之間的交易行為,客戶端繼進行消費,也從事生產,但卻非自產自銷,而是將產品賣給網路上的其他客戶,形成獨特的 C2C 市場。
72 |
73 | 在早期的 C2C 市場中,由 eBay, Yahoo, 露天等網路拍賣市集所形成的市場已經越來越成熟,這些市場透過宅配等通路,形成了一個實體的 C2C 市場結構。
74 |
75 | 接著、iPad 與 Kindle 的成功讓「數位產品」得以形成一個 C2C 的市場結構,這個結構是最近幾年來的改變重心之所在,「iPod、數位音樂、iPad、手機、App、行動裝置、電子書、線上電影」等都是在此一 C2C 結構下的產品。
76 |
77 | 但是、上述的 Stallman, Lessig, Swartz 與 Assange 等人,他們並非像 Steve Jobs 這樣用商業方法改變世界的人,而是用「政治方法」企圖改變世界的人。
78 | 這代表我們的世界很可能將進入一個由「資訊技術」所驅動的「政治改變」時期,而「資訊的揭露」則是此一改變的起點。
79 |
80 | ### 工業文明的政治結構
81 |
82 | 第二波的工業革命,推翻了原本「貴族統治」的封建莊園結構,並將世界帶進了「資本主義」結構,在「資本主義」的結構下,有幾個不同的實現方式,
83 | 一種是「自由市場型的議會制度」,像是「英、美」等國的發展路線,一種是從「極權型的國家資本主義」,像是「德國、日本」等國的發展路線。
84 | 另外還有一種不屬於「自由市場」,而且是反「資本主義」的發展方式,那就是「共產主義」。
85 |
86 | 雖然這些主義之間有很大的不同,但是在讓得「大量生產、大量消費」的基礎上,同樣有「生產集中化、產品標準化、工作專門化、生產同步化、
87 | 規模極大化、管理集權化」的特性。
88 |
89 | ### 資訊文明的政治結構
90 |
91 | 但是在第三波的資訊文明中,透過電腦與網路,我們似乎正在解構這種「大量生產、大量消費」的「極權化」情況,雖然在很多資訊產品上,大量生產與消費
92 | 的現像比之前更加嚴重,但是在網路這個技術的影響下,C2C 的市場正在快速成長,少量多樣的市場也逐漸茁壯,人們對取得「資訊」的渴望,逐漸從
93 | 「程式領域」延伸到「一般性文章與影片」,然後再延伸到「政治性文件與影片」。
94 |
95 | 未來、網路與資訊科技會帶領我們建立怎麼樣的一個「政治結構」呢?這是筆者很想知道,但卻也還在探索當中的一個重要關注項目啊!
96 |
97 | ### 參考文獻
98 | * [開放原始碼之父–Richard Stallman], 程式人雜誌 2013 年 3 月號
99 | * [Markdown 與 RSS 的創造者-Aaron Swartz], 程式人雜誌 2013 年 4 月號
100 | *
101 | * 維基百科:[勞倫斯·雷席格]
102 | *
103 | * 維基百科:[朱利安·阿桑奇]
104 | * [英國厄瓜多爾或商談阿桑奇去留問題](http://www.apdnews.com/news/27457.html), 作者:亞太日報綜合報導 發稿地:香港 時間:2013-6-03
105 | *
106 | * [第三波 (The Third Wave)], 作者:艾文‧托佛勒 (Alvin Toffler), 譯者:黃明堅, 時報出版社, 1994年06月20日.
107 | * [第三波 - 農業、工業與資訊文明](http://ccckmit.wikidot.com/thethirdwave), 陳鍾誠的網站。
108 |
109 |
110 | [開放原始碼之父–Richard Stallman]:https://dl.dropboxusercontent.com/u/101584453/pmag/201303/htm/people1.html
111 | [Markdown 與 RSS 的創造者-Aaron Swartz]:https://dl.dropboxusercontent.com/u/101584453/pmag/201304/htm/people2.html
112 | [勞倫斯·雷席格]:http://zh.wikipedia.org/wiki/%E5%8B%9E%E5%80%AB%E6%96%AF%C2%B7%E9%9B%B7%E5%B8%AD%E6%A0%BC
113 | [朱利安·阿桑奇]:http://zh.wikipedia.org/wiki/Julian_Assange
114 | [第三波 (The Third Wave)]:http://www.books.com.tw/exep/prod/booksfile.php?item=0010069728
115 |
116 | 【本文由陳鍾誠取材並修改自維基百科】
117 |
118 |
119 |
--------------------------------------------------------------------------------
/source/message1long.md:
--------------------------------------------------------------------------------
1 | ## 資訊政治:台灣「鍵盤革命」的歷史與近況
2 |
3 | ### 台灣的鍵盤革命
4 |
5 | 「鍵盤革命」雖然是最近才開始為人所知一個名詞,但是卻是我們很多人過去十年來一直在做的事情,特別是那些使用 facebook 等社群網站,
6 | 與部落格網誌寫文章評論政治的人,所不斷推動的事情。
7 |
8 | 但是要訴說台灣「鍵盤革命」的故事,我們將從一個很不政治的故事開始:
9 |
10 | ### 莫拉克風災的網路救援
11 |
12 | 2009 年 [中度颱風莫拉克] 掃過台灣,雖然風速不算很強,但卻帶來超大豪雨,結果導致了 [八八水災] ,並引發了嚴重的山崩與土石流事件,
13 | 其中以位於高雄縣甲仙鄉小林村小林部落滅村事件最為嚴重,造成數百人活埋。
14 |
15 | 台灣政府的救災行動指揮系統反應緩慢,結果很多「程式人」與「部落客」開始利用網路 (Blog、Google Map,...) 進行災情資訊彙整,
16 | 如以下 PTT 的文章所寫的一樣:
17 |
18 | * PTT 精華區 - 閱讀文章 (Emergency) --
19 |
20 | > 知名部落客比利潘率先發難,當天深夜以 Google Map 模式標明災情資訊,發展出「莫拉克颱風災情地圖」(http://bit.ly/KKDVh),並號召義工將網路上陸續傳出的災情逐筆標
21 | 示,兩天內標示了超過1200個救災情報,Google 也將此努力成果納入台灣官方首頁( )。
22 | >
23 | > 曾因破解總統府預錄治國週記而聲名大噪的網友 XDite,這次也不再惡搞,身為程式設計師的她使出渾身解數架設網站,僅花一個小時,在8月9日凌晨1點讓「莫拉克颱風災情支
24 | 援網」( )率先上線。
25 | >
26 | > 她當天徹夜不眠,讓這個網站在龐大流量湧入,仍屹立不搖,成為「唯一」沒掛的民間救災網站。XDite 說:「架網站傳遞訊息,讓災民獲救,讓家屬心安,是我唯一能做,而且
27 | 做得非常好的一件事。」
28 | > 台灣數位文化協會理事長徐挺耀與他的伙伴們,這一夜同樣熱血沸騰一場SKYPE網路會議後,8月9日凌晨3點左右「莫拉克災情網路中心」( )開始
29 | 運作,該協會長期與政府合作投入縮短數位落差工程,此次也成為唯一進駐中央及地方災害應變中心協助整合災情資訊的民間團體。
30 | >
31 | > 同一天夜裡,從未有顯赫名氣的網友 Rickz、Shadow 兩人熬夜架設「莫拉克災情資料表」( ),於8月9日凌晨3點上線;災情通報告一段落後,該網站開始倒數計時預告即將關閉,最後Rickz發表標題為「不管再過多久本站也不會關閉」的文章平息風波。
32 | >
33 | > Rickz 說:「這個網站的目的就是為了幫助人,今後不管受到什麼樣的壓力,只要還能再幫助一個人、再救一條人命,那就是對的事情,就要堅持下去。」
34 | >
35 | > 全台灣最大網路社群 PTT(批踢踢實業坊, )同樣沒在這一夜缺席,網友 waterdisney 凌晨2點42分發文提議PTT網友共組「救災團」,不到20分鐘,站長開設
36 | Emergency專版,由他擔任總召,包括合購物資、募集志工與物資、出動醫療團等任務他們逐一完成,終於在8月22日救災工作告一段落後總辭。
37 | >
38 | > waterdisney 說:「這是我活到 25 歲為止,最忙,最沈重,但卻是最有意義的一周,不會因為什麼都沒做而後悔。」
39 | >
40 | > 阿宅反抗軍發起人、奇幻藝術文化基金會執行長朱學恒指出,這次政府並未提供任何橋接口,是網友以先進技術「強行介入」,主導災情資訊通報,讓政府很不堪,但關鍵處理災
41 | 情的能力仍掌握在政府手裡,「因此當網友得到比政府多 100 倍的資訊,認為政府無能的程度也增加了100倍。」
42 | >
43 | > 不少人拿 921 地震時救災經驗與此次風災相比,卻罕見人將焦點聚焦在「網友」身上。根據資策會統計,民國 88 年 6 月,我國 12 歲以上的上網人口甫突破 400 萬人;但行政院研考會
44 | 去年進行調查,我國 12 歲以上國民上網率已達 68.5%,換算為人口約 1371 萬人,上網人口足足增加近千萬。
45 | >
46 | > 朱學恒直言,「網民即國民,國民即網民」的時代已經來臨,當幾乎所有國民都會上網,一旦網友對政府施政不滿意,政府民調滿意度自然很差,「政府官員若還不懂網路,那就
47 | 完蛋了!」
48 | >
49 | > 許多人認為,網友大多是足不出戶、不關心社會的阿宅,但這個颱風夜,這群網友有名也好,無名也罷,齊心為台灣盡心盡力,搖身一變成為凝聚台灣團結力量的關鍵英雄,或許
50 | 這也是台灣將進入網路世代的新契機。
51 |
52 | 莫拉克風災是我第一次看到「網友們」展現政治力量的事件,雖然這件事情很不政治,但是基於孫中山的名言:「管理眾人之事便是政治」,我們看到當政府失能的時候,網友們透過網路進行救災,彌補掉政府的無能,讓資訊得以快速流通的的「政治事件」。
53 |
54 | ### 洪仲秋被虐死引發 25 萬人上凱達格蘭大道
55 |
56 | 然後,在 2013 年,我們看到了一次「重要的網路政治事件」,那就是最近因「[洪仲秋被虐死一案]」,透過 [公民 1985 行動聯盟] 這個網路組織的協調,引發了 2013/8/3 日 25 萬人上凱達格蘭大道包圍總統府,卻又盡可能排除政黨介入的情況下,仍然表現出高度的組織能力,以及保持了良好秩序的事件。
57 |
58 | 以下的空拍圖片為這個事件留下了一個重要的見證,這是「鍵盤革命」的重要里程碑,也是台灣「網路世代」開始參與政治運動的一個明證。
59 |
60 | 
61 |
62 | * 圖片來源:親愛的芭樂人類學家專欄, 25萬人上街抗議真的有用嗎?, 2013/08/05 公民運動 政治 洪仲丘 社會運動
63 | *
64 |
65 | ### 零時差政府 -- g0v 組織
66 |
67 | 但是、以上兩個事件我想代表了「網路世代」政治力量的匯集結果。但事實上、在網路上隨時都有很多零星的組織,不斷的進行著「鍵盤革命」,以我個人比較熟悉的
68 | 程式領域而言,就看到了像「g0v」這樣企圖用公開政府資訊的方式,改變政治的組織,還有像「Code for tomorrow」這個仿照美國「Code for America」的組織,企圖用柔性的方式,「寫程式改造社會」的組織,以下是這些組織的網址:
69 |
70 | * 零時政府 --
71 | * Code for Tomorrow --
72 | * Code for America --
73 |
74 | ### 教育界的網路小革命
75 |
76 | 另外、在教育領域,也有一些組織與個人正在進行著網路小革命,像是 Khan Academy 的 Salman Khan 就透過網路,讓美國小學到高中的教育有了很大的改變,
77 | 產生了「翻轉教學法」等更適合網路的做法,我最近也用 Khan Academy 來教小孩「用英文學數學」。
78 |
79 | 而像 Sugata Mitra 在「建立雲端的學校」這個 TED 演講中,也闡述了他在教育上利用電腦與網路來讓那些極度貧窮無法接觸電腦的小孩,透過自我學習
80 | 所發展出的獨特方法,也是非常令人感動的,該影片的網址如下。
81 |
82 | *
83 |
84 | 另外、像是我個人、還有洪朝貴、彭明輝、李家同、洪士翰等人,也常常撰寫關於教育方面的文章,希望能透過這樣的分享,讓大家更清楚教育現在所遭遇到的困境,
85 | 並且嘗試著用各種方法來改變教育的缺陷。
86 |
87 | 我相信像這樣的小革命,正是匯聚出以上較大事件的動力,而政治的現況也終將會被網路所改變,至於會如何改變,則是目前所難以預言的了!
88 |
89 | ### 網路政治組織 -- 海盜黨
90 |
91 | 最近我與 g0v 創辦人高嘉良連絡時,發現他們正在關注「柏林海盜黨」所釋出的一個實驗性開放原始碼軟體 liquidfeedback,網址如下:
92 |
93 | *
94 |
95 | 而且他們正在進行一個工作,就是將 liquidfeedback 修改為中文版,並且嘗試用這種方式改變台灣的政治環境,您可以從 github
96 | 上下載這個專案。
97 |
98 | *
99 |
100 | 以下是海盜黨的一些相關資料,請讀者參考:
101 |
102 | * 維基百科, [海盜黨國際](http://zh.wikipedia.org/zh-tw/%E6%B5%B7%E7%9B%9C%E9%BB%A8%E5%9C%8B%E9%9A%9B)
103 | * 維基百科, [德國海盜黨](http://zh.wikipedia.org/zh-tw/%E5%BE%B7%E5%9C%8B%E6%B5%B7%E7%9B%9C%E9%BB%A8)
104 | * Wikipedia:[Pirate_Party_Germany](http://en.wikipedia.org/wiki/Pirate_Party_Germany)
105 | * [「遙控民主」新實驗,讓百年大黨取經的七歲駭客政黨 - 專訪海盜黨主席(上)](http://hatetyping.blogspot.de/2013/08/blog-post_24.html)
106 |
107 | 海盜黨的一些網路民主的實施方法可以參考以下的文章:
108 |
109 | * [德國海盜黨的流動式民主](http://charlesc.ilovemeow.net/blog/20130110/1202)
110 |
111 | 我們將上述文章的重點摘要如下:
112 |
113 | * 2011 年,德國海盜黨針對柏林州議會選舉推出 15 位候選人,全上。其後幾次其他的州議會選舉,德國海盜黨也獲得7-8%的得票率,取得席次。
114 | * 海盜黨的多數的決策都是先在網路上經過許多人的討論,例如用 [PiratePad]、聊天室、wiki 和郵件論壇來協作。
115 | * 投票時,每人一票。但是,因為並非大家都能夠詳閱政策內容,所以系統允許成員可以委託他人代為投票。委託範圍可以是所有提案、某個主題的提案、或是某特定提案。而被委派投票的成員,還可以把這些票、包括自己的一票,再度委託給他人投票!
116 | * Liquid Feedback 這種以信任為基礎的模式,類似信譽系統(reputation system),只不過成員的參與所換到的不是點數,而是選票。理論上,這種投票鏈可能會把票集中到人緣好的菁英或獨裁者身上,但好在有個防錯機制,可以在任何時候取消委託投票,有野心的海盜也得認真才能成事。Bormuth 說,我們讓有戰鬥力的人可以成事,但也讓大家有權控制這些人。
117 |
118 | ### 結語
119 |
120 | 雖然德國的國情與台灣不同,不過在網路時代,各國的做法都可以很透明的被大家所參考模仿,然後經過嘗試後找到一個比較適合自己國家的實施方式,
121 | 運用網路來改變政治結構啊!
122 |
123 | ### 參考文獻
124 | * [工程師的鍵盤革命:拆政府,原地重建](http://www.inside.com.tw/2013/08/05/coscup-2013-coders-keyboard-revolution), inside 網站。
125 | * [PTT 精華區 - 閱讀文章 (Emergency)](http://www.ptt.cc/man/Emergency/D8B1/M.1252037298.A.654.html)
126 | * 維基百科:[中度颱風莫拉克]
127 | * 維基百科:[八八水災]
128 |
129 | [中度颱風莫拉克]:http://zh.wikipedia.org/zh-tw/%E9%A2%B1%E9%A2%A8%E8%8E%AB%E6%8B%89%E5%85%8B_(2009%E5%B9%B4)
130 | [八八水災]:http://zh.wikipedia.org/wiki/%E5%85%AB%E5%85%AB%E6%B0%B4%E7%81%BD
131 | [洪仲秋被虐死一案]:http://zh.wikipedia.org/zh-tw/%E6%B4%AA%E4%BB%B2%E4%B8%98%E6%9E%89%E6%AD%BB%E4%BA%8B%E4%BB%B6
132 | [公民 1985 行動聯盟]:http://zh.wikipedia.org/wiki/%E5%85%AC%E6%B0%911985%E8%A1%8C%E5%8B%95%E8%81%AF%E7%9B%9F
133 | [PiratePad]:http://www.piratenpad.de/
134 |
135 | 【本文由陳鍾誠取材並修改自維基百科】
136 |
137 |
--------------------------------------------------------------------------------
/code/oc/as1_bak.js:
--------------------------------------------------------------------------------
1 | var fs = require("fs");
2 | var util = require("util");
3 | var c = require("./ccc");
4 | var opTable = require("./cpu1").opTable;
5 | var Memory = require("./memory");
6 |
7 | var parseR = function(str) {
8 | var rmatch = /R(\d+)/.exec(str);
9 | if (rmatch == null)
10 | return NaN;
11 | return parseInt(rmatch[1]);
12 | }
13 |
14 | var Assembler = function() {
15 |
16 | this.symTable = {};
17 |
18 | this.assemble = function(asmFile, objFile) { // 組譯器的主要函數
19 | c.log("\nAssembler:asmFile=%s objFile=%s\n", asmFile, objFile); // 輸入組合語言、輸出目的檔
20 | c.log("===============Assemble=============\n");
21 |
22 | var text = fs.readFileSync(asmFile, "utf8"); // 讀取檔案到 text 字串中
23 | this.lines = text.split(/[\r\n]+/); // 將組合語言分割成一行一行
24 | c.log(this.lines);
25 |
26 | this.pass1(this.lines); // 第一階段:計算位址
27 | c.log("===============SYMBOL TABLE=========\n"); // 印出符號表
28 | for (s in this.symTable) {
29 | c.log("%s %s\n", c.fill(' ',s,8), c.hex(this.symTable[s].address, 4));
30 | }
31 | this.pass2(this.codes); // 第二階段:建構目的碼
32 | this.saveObjFile(objFile); // 輸出目的檔
33 | }
34 |
35 | this.pass1 = function(lines) { // 第一階段的組譯
36 | var address = 0;
37 | c.log("\n=================PASS1================\n");
38 | this.codes = [];
39 | for (i in lines) { // 對於每一行
40 | if (lines[i].length == 0) continue;
41 | var code = new Code(lines[i]); // 剖析並建立 code 物件
42 | code.address = address; // 設定該行的位址
43 | if (code.label.length != "") // 如果有標記符號
44 | this.symTable[code.label] = code; // 加入符號表中
45 | this.codes.push(code);
46 | code.print();
47 | address += code.size(); // 計算下一個指令位址
48 | }
49 | }
50 |
51 | this.pass2 = function() { // 組譯器的第二階段
52 | c.log("=============PASS2==============\n");
53 | for (i in this.codes) { // 對每一個指令
54 | var code = this.codes[i];
55 | this.translate(code); // 進行編碼動作
56 | code.print();
57 | }
58 | }
59 |
60 | this.translate = function(code) { // 指令的編碼函數
61 | var ra=0, rb=0, rc=0, cx=0;
62 | var pc = code.address + 4; // 提取後PC為位址+4
63 | var args = code.args;
64 | var labelCode = null;
65 | var symTable = this.symTable;
66 | if (code.op.type == "N") {
67 | code.obj = c.hex(code.op.id, 2) + c.hex(0, 6);
68 | } else if (code.op.type == "C") {
69 | ra = parseR(args[0]);
70 | rb = parseR(args[1]);
71 | cx = parseInt(args[2]);
72 | code.obj = c.hex(code.op.id, 2)+c.hex(ra, 1)+c.hex(rb, 1)+c.hex(cx, 4);
73 | } else if (code.op.type == "L") {
74 | ra = parseR(args[0]);
75 | rb = 15;
76 | labelCode = symTable[args[1]];
77 | cx = labelCode.address - pc;
78 | code.obj = c.hex(code.op.id, 2)+c.hex(ra, 1)+c.hex(rb, 1)+c.hex(cx, 4);
79 | } else if (code.op.type == "D") {
80 | var unitSize = 1;
81 | switch (code.op.name) {
82 | case "RESW": // 如果是 RESW
83 | case "RESB": // 或 RESB
84 | code.obj = c.dup('0', code.size()*2);
85 | break;
86 | case "WORD": // 如果是 WORD:
87 | unitSize = 4;
88 | case "BYTE": { // 如果是 BYTE : 輸出格式為 %2x
89 | code.obj = "";
90 | for (i in args) {
91 | if (args[i].match(/\d+/)) // 常數
92 | code.obj += c.hex(parseInt(args[i]), unitSize*2);
93 | else { // 標記
94 | labelCode = symTable[args[i]];
95 | code.obj += c.hex(labelCode.address, unitSize*2);
96 | }
97 | }
98 | break;
99 | } // case BYTE:
100 | } // switch
101 | } // if
102 | }
103 |
104 | this.saveObjFile = function(objFile) {
105 | c.log("\n=================SAVE OBJ FILE================\n");
106 | var obj = "";
107 | for (i in this.codes) {
108 | obj += this.codes[i].obj;
109 | }
110 | c.log("%s\n", obj);
111 |
112 | var m = new Memory(1);
113 | m.loadhex(obj);
114 | m.save(objFile);
115 | }
116 | }
117 |
118 | var Code = function(line) {
119 | this.print = function() {
120 | c.log(this.toString());
121 | }
122 |
123 | this.toString = function() {
124 | return util.format("%s %s %s %s %s %s", c.hex(this.address,-4),
125 | c.fill(' ',this.label,8), c.fill(' ',this.op.name, 8),
126 | c.fill(' ',this.args, 16), c.hex(this.op.id,2), this.obj);
127 | }
128 |
129 | this.size = function() {
130 | switch (this.op.name) { // 根據運算碼 op
131 | case "RESW" : return 4 * parseInt(this.args[0]); // 如果是 RESW, 大小為 4*保留量(參數 0)
132 | case "RESB" : return 1 * parseInt(this.args[0]); // 如果是 RESB, 大小為 1*保留量(參數 0)
133 | case "WORD" : return 4 * this.args.length; // 如果是WORD, 大小是 4*參數個數
134 | case "BYTE" : return 1 * this.args.length; // 如果是BYTE, 大小是 1*參數個數
135 | case "" : return 0; // 如果只是標記, 大小為 0
136 | default : return 4; // 其他情形 (指令), 大小為 4
137 | }
138 | }
139 |
140 | var labCmd = /^((\w+):)?\s*([^;]*)/;
141 | var parts = labCmd.exec(line); // 分割出標記與命令
142 | this.label = c.nonull(parts[2]); // 取出標記 (\w+)
143 | var tokens = parts[3].split(/[ ,\t\r]+/); // 將命令分割成基本單元
144 | var opName = tokens[0]; // 取出指令名稱
145 | this.args = tokens.slice(1); // 取出參數部份
146 | this.op = opTable[opName];
147 | this.obj = "";
148 | }
149 |
150 | var argv = process.argv;
151 | var a = new Assembler();
152 | a.assemble(argv[2], argv[3]);
153 |
154 | module.exports = Assembler;
--------------------------------------------------------------------------------
/code/oc/vm0.js:
--------------------------------------------------------------------------------
1 | var c = require("./ccc");
2 | var cpu1 = require("./cpu0");
3 | var Memory = require("./memory");
4 |
5 | var isDump = process.argv[3] == "-d";
6 |
7 | var IR = 16, PC = 15, LR = 14, SP = 13, SW = 12;
8 | var ID = function(op) { return cpu1.opTable[op].id; }
9 |
10 | var run = function(objFile) {
11 | R = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 13, -1, 0, 16];
12 | m = new Memory(1);
13 | m.load(objFile);
14 | if (isDump) m.dump();
15 | var stop = false;
16 | while (!stop) { // 如果尚未結束
17 | var tpc = R[PC];
18 | R[0] = 0; // R[0] 永遠為 0
19 | R[IR] = m.geti(R[PC]); // 指令擷取,IR=[PC..PC+3]
20 | R[PC] += 4; // 擷取完將 PC 加 4,指向下一個指令
21 | var op = c.bits(R[IR], 24, 31); // 取得 op 欄位,IR[24..31]
22 | var ra = c.bits(R[IR], 20, 23); // 取得 ra 欄位,IR[20..23]
23 | var rb = c.bits(R[IR], 16, 19); // 取得 rb 欄位,IR[16..19]
24 | var rc = c.bits(R[IR], 12, 15); // 取得 rc 欄位,IR[12..15]
25 | var c24= c.signbits(R[IR], 0, 23); // 取得 24 位元的 cx
26 | var c16= c.signbits(R[IR], 0, 15); // 取得 16 位元的 cx
27 | var c5 = c.bits(R[IR], 0, 4); // 取得 16 位元的 cx
28 | var addr = R[rb]+c16;
29 | var raddr = R[rb]+R[rc]; // 取得位址[Rb+Rc]
30 | var N = c.bits(R[SW], 31, 31);
31 | var Z = c.bits(R[SW], 30, 30);
32 | // c.log("IR=%s ra=%d rb=%d rc=%d c24=%s c16=%s addr=%s", c.hex(R[IR], 8), ra, rb, rc, c.hex(c24, 6), c.hex(c16, 4), c.hex(addr, 8))
33 | switch (op) { // 根據op執行動作
34 | case ID("LD") : R[ra] = m.geti(addr); break; // 處理 LD 指令
35 | case ID("ST") : // 處理 ST 指令
36 | m.seti(addr, R[ra]);
37 | if (isDump) c.log("m[%s]=%s", c.hex(addr,4), m.geti(addr));
38 | break;
39 | case ID("LDB"): R[ra] = m.getb(addr); break; // 處理 LDB 指令
40 | case ID("STB"): m.setb(addr, R[ra]); break; // 處理 STB 指令
41 | case ID("LDR"): R[ra] = m.geti(raddr); break; // 處理 LDR 指令
42 | case ID("STR"): m.seti(raddr, R[ra]); break; // 處理 STR 指令
43 | case ID("LBR"): R[ra] = m.getb(raddr); break; // 處理 LBR 指令
44 | case ID("SBR"): m.setb(raddr, R[ra]); break; // 處理 SBR 指令
45 | case ID("LDI"): R[ra] = c16; break; // 處理 LDI 指令
46 | case ID("CMP"): { // 處理 CMP指令,根據比較結果,設定 N,Z 旗標
47 | if (R[ra] > R[rb]) { // > : SW(N=0, Z=0)
48 | R[SW] &= 0x3FFFFFFF; // N=0, Z=0
49 | } else if (R[ra] < R[rb]) { // < : SW(N=1, Z=0, ....)
50 | R[SW] |= 0x80000000; // N=1;
51 | R[SW] &= 0xBFFFFFFF; // Z=0;
52 | } else { // = : SW(N=0, Z=1)
53 | R[SW] &= 0x7FFFFFFF; // N=0;
54 | R[SW] |= 0x40000000; // Z=1;
55 | }
56 | ra = 12;
57 | break;
58 | }
59 | case ID("MOV"): R[ra] = R[rb]; break; // 處理MOV指令
60 | case ID("ADD"): R[ra] = R[rb]+R[rc]; break; // 處理ADD指令
61 | case ID("SUB"): R[ra] = R[rb]-R[rc]; break; // 處理SUB指令
62 | case ID("MUL"): R[ra] = R[rb]*R[rc]; break; // 處理MUL指令
63 | case ID("DIV"): R[ra] = R[rb]/R[rc]; break; // 處理DIV指令
64 | case ID("AND"): R[ra] = R[rb]&R[rc]; break; // 處理AND指令
65 | case ID("OR") : R[ra] = R[rb]|R[rc]; break; // 處理OR指令
66 | case ID("XOR"): R[ra] = R[rb]^R[rc]; break; // 處理XOR指令
67 | case ID("SHL"): R[ra] = R[rb]<>c5; break; // 處理SHR指令
69 | case ID("ADDI"):R[ra] = R[rb] + c16; break; // 處理 ADDI 指令
70 | case ID("JEQ"): if (Z==1) R[PC] += c24; break; // 處理JEQ指令 Z=1
71 | case ID("JNE"): if (Z==0) R[PC] += c24; break; // 處理JNE指令 Z=0
72 | case ID("JLT"): if (N==1&&Z==0) R[PC] += c24; break; // 處理JLT指令 NZ=10
73 | case ID("JGT"): if (N==0&&Z==0) R[PC] += c24; break; // 處理JGT指令 NZ=00
74 | case ID("JLE"): if ((N==1&&Z==0)||(N==0&&Z==1)) R[PC]+=c24; break; // 處理JLE指令 NZ=10 or 01
75 | case ID("JGE"): if ((N==0&&Z==0)||(N==0&&Z==1)) R[PC]+=c24; break; // 處理JGE指令 NZ=00 or 01
76 | case ID("JMP"): R[PC]+=c24; break; // 處理JMP指令
77 | case ID("SWI"): // 處理SWI指令
78 | switch (c24) {
79 | case 3: c.printf("%s", m.getstr(R[9])); break;
80 | case 4: c.printf("%d", R[9]); break;
81 | default:
82 | var emsg = c.format("SWI cx=%d not found!", c24);
83 | c.error(emsg, null);
84 | break;
85 | }
86 | break;
87 | case ID("JSUB"):R[LR] = R[PC]; R[PC]+=c24; break; // 處理JSUB指令
88 | case ID("RET"): if (R[LR]<0) stop=true; else R[PC]=LR; break; // 處理RET指令
89 | case ID("PUSH"):R[SP]-=4; R[ra]=m.geti(addr); m.seti(R[SP], R[ra]); break; // 處理PUSH指令
90 | case ID("POP"): R[ra] = m.geti(R[SP]); R[SP]+=4; break; // 處理POP指令
91 | case ID("PUSHB"):R[SP]--; R[ra]=m.getb(addr); m.setb(R[SP], R[ra]); break; // 處理PUSH指令
92 | case ID("POPB"):R[ra] = m.getb(R[SP]); R[SP]++; break; // 處理POPB指令
93 | default: c.error("OP not found!", null);
94 | } // switch
95 | if (isDump)
96 | c.log("PC=%s IR=%s SW=%s R[%s]=0x%s=%d", // 印出 PC, IR, R[ra]暫存器的值,以利觀察
97 | c.hex(tpc,4), c.hex(R[IR],8), c.hex(R[SW],8), c.hex(ra,2), c.hex(R[ra], 8), R[ra]);
98 | } // while
99 | }
100 |
101 | run(process.argv[2]);
102 |
--------------------------------------------------------------------------------
/source/article2.md:
--------------------------------------------------------------------------------
1 | ## JavaScript (9) – Google 的語音合成 API 之使用 (作者:陳鍾誠)
2 |
3 | ### 簡介
4 |
5 | 我還記得在 1996 年時,我到中研院許老師的實驗室當助理,做了兩年自然語言處理的相關程式,
6 | 學習到其中主要較成熟的技術像是「注音轉國字」(對應產品為自然輸入法),然後這兩年整個實驗室
7 | 還試圖去研究一些較不成熟,但卻具有挑戰性的技術,特別是「自然語言理解」領域的一些嘗試,例如
8 | 有位同事就發展出了一個有趣的程式,當您輸入小學課本中的數學問題時,該程式可以輸出該問題的解答。
9 |
10 | 自然語言技術一直是筆者相當關心的領域,雖然筆者的關注比較偏向「文字」部分,在去年於金門大學
11 | 教授「計算語言學」這門課時,我就將這些相關的技術寫成了一本書,放在筆者的 github 當中,您可以
12 | 從以下的網址找到這本書。
13 |
14 | * 陳鍾誠的教科書 --
15 | * 語言處理技術 --
16 |
17 | 但是,自然語言處理可以說是一門既深奧又困難的領域,雖然研究了很久,但筆者一直還沒有去觸碰
18 | 「語音合成」與「語音辨識」這兩個領域的主題,對這種「語音領域」的東西可以說是既期待又怕受傷害啊!
19 |
20 | 不過、現在由於「微軟」與 Google 等軟體大廠,都已經投入了非常多的資源在研究這些先進的領域,
21 | 並且製作出了足以商品化的功能,因此我們只要善用他們所釋出的 API,就可以輕鬆的應用這些功能了。
22 |
23 | 在本文中,我們將介紹如何使用 HTML+JavaScript 技術,去使用 Google 所提供的「語音辨識與合成」的服務。
24 |
25 | ### 語音合成的 Google 服務
26 |
27 | Google 的語音合成服務非常容易使用,因為您只要利用 Google 翻譯中的 TTS (Text to Speech) 功能,將
28 | 文字放到以下網址中的 {query} 欄位中,然後設定正確的語言欄 {lang},就可以取得這句話的語音檔了。
29 |
30 | > http://translate.google.com/translate_tts?ie=utf-8&tl={lang}&q={query}
31 |
32 | 舉例而言,假如您想讓瀏覽器說出 Text to speech 這句英文,只要將 {lang} 設為 en,然後將 {query} 設為 Text to speech
33 | 即可,您可以點選下列網址聽到 Google 所合成的語音。
34 |
35 | * [http://translate.google.com/translate_tts?ie=utf-8&tl=en&q=Text to speech](http://translate.google.com/translate_tts?ie=utf-8&tl=en&q=Text to speech)
36 |
37 | 如果您想讓瀏覽器說中文,那麼 {lang} 欄位就必須要設定為 zh,例如您可以點選下列網址廳到「語音合成」這句話。
38 |
39 | *
40 |
41 | 一但瞭解了 Google TTS 功能的使用方式之後,您就可以很容易的在網頁中嵌入這樣的「功能元件」了。
42 |
43 | 在 HTML 5.0 當中有個特殊的標記, 可以在網頁中嵌入語音,那就是 `` 標記,您只要在 src 欄位中
44 | 填入正確的語音檔網址,該標記就可以用來控制語音的播放,如果您在 `` 當中加上 controls 這個屬性,那麼
45 | 畫面上就會出現一個像錄音機的控制面版,讓你自行操控語音的「播放與暫停」等功能。
46 |
47 | 舉例而言,以下是一個很簡單的程式,其中有兩個「語音控制項」,一個按下後可以播放「你好、這是谷歌的語音合成測試!」
48 | 這句中文,另一個按下後可以播放「Hi! This is the text to speech function of Google.」這句英文。
49 |
50 | 
51 |
52 | 您可以透過這樣的控制項,控制「播放、暫停、調整音量」等等功能,上述畫面的 HTML 原始程式碼如下:
53 |
54 | 檔案:textToSpeech1.html
55 | 網址:
56 |
57 | ```HTML
58 |
59 |
60 |
61 |
62 |
63 | 中文 (zh): 你好、這是谷歌的語音合成測試!
64 |
65 |
66 | 英文 (en): Hi! This is the text to speech function of Google.
67 |
68 |
69 | ```
70 |
71 | 說明:必須注意的一點是,目前並非每種瀏覽器都有支援 `` 標記,而且下節當中所使用的 JavaScript 程式也不見得都能正常運作,
72 | 像是在 IE 9.0 當中就似乎不支援 audio 標記,但是在 Firefox 22.0 與 Google Chrome 28.0 當中就支援了 audio 標記,而且
73 | 以下程式均能正常運作。
74 |
75 | ### 使用 JavaScript 控制 audio 元件
76 |
77 | 有時,我們不希望出現預設的語音控制項,但是卻又希望在某些按鈕被按下時能夠合成語音,這時候我們就需要撰寫一些 JavaScript 程式來控制
78 | audio 元件的播放行為,這時我們可以呼叫 audio 元件的 play() 函數,以進行播放動作。舉例而言,以下程式就改用了按鈕控制
79 |
80 | 
81 |
82 | 檔案:textToSpeech2.html
83 | 網址:
84 |
85 | ```html
86 |
87 |
88 |
89 |
90 |
91 | 中文 (zh): 你好、這是谷歌的語音合成測試!
92 | 播放
93 |
94 |
95 | ```
96 |
97 | 當然、上述的程式用途不大,因為播放的語句是固定的,如果我們想讓網頁能播放使用者輸入的內容,就必須要動態的在 audio 元件的
98 | src 欄位當中,塞入使用者所輸入的文字,以下程式示範了這樣的功能。
99 |
100 | 檔案:textToSpeech3.html
101 | 網址:
102 |
103 | ```html
104 |
105 |
106 |
107 |
115 |
116 |
120 | 播放
121 |
122 |
123 | ```
124 |
125 | 在上面的程式中,我們在 button 「播放」按鈕按下時,會呼叫下列指令去播放 text 這個 textarea 中的文字。
126 |
127 | ```javascript
128 | playAudio('audio1', 'zh', document.getElementById('text').value);
129 | ```
130 |
131 | 而在 playAudio() 函數中,我們用下列指令設定 audio 控制項的語音網址為 Google TTS 的網址,然後播放,如下程式碼所示:
132 |
133 | ```javascript
134 | var audio = document.getElementById(id); // 取得 audio 控制項
135 | audio.src = "http://translate.google.com/translate_tts?ie=utf-8&tl="+lang+"&q="+text; // 設定語音為 google TTS。
136 | audio.play(); // 播放語音。
137 | ```
138 |
139 | 原本其實只要上述三行就夠了,但是由於在 Chrome 當中,audio 控制項在呼叫完 play() 之後,似乎並不會自動回到開頭,
140 | 導致第二次的無法播放聲音 (因為已經在最後了),因此才需要加入下列這行,強制 play() 函數在播放完成之後回到開頭,
141 | 以便在下一次播放時能聽得到聲音。
142 |
143 | ```javascript
144 | audio.addEventListener('ended', function(){ this.currentTime = 0; }, false); // 當播放完畢,強制回到開頭。
145 | ```
146 |
147 | ### 結語
148 |
149 | 現在、我們已經講解完整個 Google 語音合成 API 的使用方式了,筆者覺得 Google 的這種設計方式其實很棒,讓我們可以
150 | 很容易的在任何網頁中加入 Text to Speech 的功能,而且不需要安裝任何的軟體。
151 |
152 | 不過、筆者發現目前的Google 語音合成服務還有幾個小問題,例如在中文的模式下,如果夾雜英文的時候,Google TTS 會用
153 | 逐字的方式念初英文。舉例而言,假如我們想讓 Google TTS 念初下列文章。
154 |
155 | > Hello, 你好!
156 |
157 | 則 Google TTS 所念出的語句,將會變成下列情況:
158 |
159 | > H. e. l. l. o, 你好!
160 |
161 | 這聽起來很怪!但可惜的是,筆者還不知道有沒有甚麼方法可以讓 Google TTS 平順的念出中文中所夾雜的英文,如果有人知道
162 | 也請告訴我!
163 |
164 | 不過如果將 {lang} 欄位設定為 en (英文模式),那麼 Google TTS 就可以平順的念出英文,而且品質還不錯。所以目前如果要
165 | 做中英夾雜的發音,可能要用 JavaScript 自行將中英文切割,然後利用類似下列方法,自行切換 {lang} 欄位,以便能順利的念出
166 | 中英夾雜的句子,只是這樣真的很不方便就是了。
167 |
168 | ```javascript
169 | audio.addEventListener('ended', function() { .....} );
170 | ```
171 |
172 | 在下期當中,我們將會繼續探討有關 Google 語音服務的主題,不過不再是「語音合成」 (Text to Speech) 了,而是「語音辨識」
173 | (Speech to Text)。
174 |
175 | 這是一個在技術上更困難的主題,不過幸運的是,Google 已經幫我們完成了這些程式,我們只要懂得如何用 JavaScript 呼叫就行了。
176 |
177 | ### 參考文獻
178 | * [Google Text-To-Speech (TTS)](http://weston.ruter.net/2009/12/12/google-tts/)
179 | * [The Unofficial Google Text-To-Speech API](http://techcrunch.com/2009/12/14/the-unofficial-google-text-to-speech-api/)
180 |
--------------------------------------------------------------------------------
/htm/discuss1long.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
21 |
22 |
受到 2013/8/3 時 25 萬人上凱達格蘭大道這件事的激勵,讓我想到能否號召網友們,形成一個沒有實體領土,只有虛擬領土的「網路國家」呢?
23 |
透過這個國家,我們可以制定法律、提出政策、甚至發動資訊戰。
24 |
然後這些網民仍然是某些實體國家(例如台灣)的國民,因此仍然具有該國的投票權,所以就可以透過「網路公投」決定政策後, 要求政黨或立委認養這些政策並簽下契約,以換取將這些網民的票投給他們的「交易」。
25 |
我認為這種方式讓網民可以有效的影響政府,並且跨過「公投法門檻過高」的問題。
26 |
於是我發了以下的訊息在「程式人雜誌的討論區」以及自己的 facebook 上:
27 |
問題:我想我又瘋了,今年初我辦了一本新的雜誌,現在居然想成立一個新的國家 (「網路公民國」 )
28 |
原始討論網址: https://www.facebook.com/groups/programmerMagazine/permalink/690675390949180/
29 |
回應訊息:
30 |
31 | P○○ 陳老師,此處所謂之「國家」是指「真的國家」還是某個「網路社群」?
32 | 陳○○ 所謂的國家構成是 公民 主權 領土 能有支持者,在網路的領土上,就具備有一定的影響力,如果這樣說來,創造所謂"跨形式國界"的國家,也不是不可能的。
33 | 陳鍾誠
34 |
35 | 其實目前沒有一定的定義,這個慨念是流動發展中的。我想用「虛擬國家」這個詞彙,或許比較能抓到這類的國家概念,
36 | 不是只有一個社團,而且有「憲法、虛擬領土、主權」、也可以宣戰,媾和。
37 |
38 | E○○ 關於宣戰....網路戰爭,也是一種戰爭。例如:廣大興號事件和菲律賓之間的鍵盤戰爭。
39 | P○○ 陳○○,抱歉,法律不是我的專業,我也不是要潑冷水,而是真的真的很有興趣想瞭解,所以向您請教一下。
40 |
41 | 如果某國「公民 (網路鄉民)」的實體生命需靠其他國家 (如中華民國) 提供保障;「主權」需靠網路業者提供等價服務;「領土」則存在於電子訊號充斥的網路空間及各式儲存設備中,那麼…
42 |
43 | 外敵侵犯該國公民實體生命時,該國的對策是?
44 |
45 |
46 | 網路服務斷線時,維護主權的對策是?
47 |
48 |
49 | 停電斷訊或是儲存資料遺失時,該國的領土位置是?
50 |
51 | 又,如果真的要「脫離母國,自立門戶」,那麼該國公民在離線 (等同出國) 的時候,是否應依法向中華民國申請簽証才能把網路設備關掉呢?且若是中華民國不發簽証的話,那麼離線和偷渡的差異是?
52 |
53 | 陳鍾誠 我在想,由於全球化的時代來臨,即使一個國家封鎖網路,也不可能全世界的網路都封起來,所以虛擬國仍然可以活著。
54 | 陳鍾誠
55 |
56 |
57 | 外敵侵犯該國公民實體生命時,該國的對策是?
58 |
59 | 當網民遭受不合理對待時,網路公民國可以禁止該國存取「網路公民國」的一切線上資源,作為報復!
60 |
61 | 陳○○
62 |
72 | 陳鍾誠
73 |
74 |
75 | 網路服務斷線時,維護主權的對策是?
76 |
77 | 至少在兩個以上國家的雲端分站,因此斷線應該也不是問題。
78 |
79 | 陳鍾誠
80 |
81 |
82 | 停電斷訊或是儲存資料遺失時,該國的領土位置是?
83 |
84 | 兩個以上的備援,因此認一個停電資料都不會遺失,甚至會放在 Amazon EC2 或 Google 服務上,或者 Github 等,因此這個國家根本不需要固定的領土。
85 |
86 | 陳鍾誠 有朋友說這樣報復有點邪惡 ....
87 |
88 | 我用這的例子想說明的是,網路虛擬國家仍然是有能力與真實國家對抗的,但並不見得要這樣做。
89 | 網路國家運作的方法,應該還是會取決於類似公民投票的方式,即使要宣戰,也必須要網路公民投票啊!
90 |
91 | F○○ http://g0v.tw/ 也許可以找到志同道合的人
92 | S○○ 沉默的艦隊…
93 | 黃○○ 你超和平 ok的
94 | E○○ P○○ 1. 外敵侵犯該國公民實體生命時,該國的對策是?
95 |
98 | P○○
99 |
100 | E○○ 假設某 A 為網路公民國之公民。他在離線 (出國) 並偷渡到中華民國某市某街巷口的便利商店利用中華民國的貨幣購買午餐時被歹徒殺害。依您的建議,某 A 之親屬朋友向美國白宮發起連署。
101 | 上述的情境中,哪一個部份是「網路公民國」對其公民提供的保障?又,假設中華民國的確向網路公民國交出行兇的人犯,網路公民國將如何處置?剝奪該人終生上網的權利?
102 |
103 | E○○ P○○ 如果可以改你的問題:
104 |
105 | 我會改成「網路」向「政府」要求交出人犯並處置。(就像這次1985聯盟一樣) 網路可以是社群、團體、聯盟、組織....也許未來可以叫國家、地球聯邦、星際聯邦、宇宙XX什麼的.....只是名字的差別。
106 | 或許有人會支持「英雄聯盟」也不一定...開玩笑,幽默一下...虛擬的背後有實體,雖然虛擬不能完全取代實體,比如開心農場的拔回來的菜是不能吃的,SF(特種部隊)中彈之後人也不會死.....虛擬世界可以輔助真實世界,比如網路戀愛,最後結婚。又如網路可以人肉,但是最後還是要靠實體的警察來抓人。善用網路讓世界更美好,至於怎麼用?就要靠大家了....
107 |
108 | A○○ http://www.haodoo.net/?M=book&P=1272 黃仁宇《中國大歷史》 有意思。我以前也讀過一本中國通史, 也是感觸良多。找時間讀讀。
109 | 陳鍾誠 可否請大家幫忙分享我這篇文章呢? https://www.facebook.com/notes/陳鍾誠/網友們鄉民們讓我們建立一個國家吧/10151749889981893
110 | 陳鍾誠 非常建議看黃仁宇的「資本主義與 21 世紀」。
111 | A○○ 這主意有“三把火”的感覺。當初那些魯蛇都是非自願也非計劃的做出那些行為,是被迫的邊移動邊開火。但其成果確演化演變成偉大的事件。與現況相比個人認為有差距。
112 | P○○
113 |
114 | 陳老師您好,不知能否在您的版面回應,如果老師覺得不對,不好,不妥,請和我說,我一定刪除並加道歉。我期待大國民、小政府的時代來臨。
115 | 在那之前,我不認為「因為我們的政府或是制度很糟,而我們的鄉民很有力量,所以我們乾脆像五月花的先輩一樣脫離母國,而去建立一個不只是社群,而是國家為名的組織,有『憲法、虛擬領土、主權」、也可以宣戰,媾和!』」是一個好的解決方法。
116 | 自己的 bug 自己解,自己的國家自己救。
117 | 真抱歉,我知道講這些一定很礙眼。誠心地說聲 SORRy。
118 |
119 | 陳鍾誠 非常歡迎 P○○ ,我已經將您加為好友,也可以私訊給我!
120 | T○○ 分裂國土, 如果是實際的領土或領海的話, 會觸犯刑法的,但是如果只是喊爽用的網路上的虛擬國度,如果不涉及實際的領土或領海, 應該是無罪的
121 |
122 |
123 |
126 |
127 |
128 |
--------------------------------------------------------------------------------