Scarky 您的博客線上檢測系統

Scarky 提供線上出程式題目的平台

出了一道好题目却不知道该怎样投递到各大OJ上?现在不用担心这个问题了,因为你可以直接把自己的Blog变成一个OJ。Scarky是一个建立在SPOJ系统上的OJ平台。所不同的是,任何人无需注册便可以编写自己的题目并发在自己的网站上与网友分享,并且网友们提交答案时也不需要进行注册。这个网站的功能还在不断扩充中,但目前就Programming Challenge模块看来,这个网站已经很强大了。以后我有了好题目就用这种方式和大家分享了,这里先试用一下,题目来源好像是某次USACO月赛。

matrix67 的說明
Scarky 網址點我

創建題目

  • 點進網站,點選創建自己的題目,您將會看到下圖的訊息,記得要求它寄封題目鏈結到你的信箱。這些題目內容稍後還能修改。
    scarky5.png
  • 在信封中,將會收到編輯頁面鏈結。
    scarky3.png
  • 回到編輯頁面,將可以把輸入輸出測資放上去,最後按儲存訊息即可。
    基本上這裡都採用嚴格比對,也就是多空白多換行字符都是不行的。
    scarky2.png
  • 編輯者還能看到目前的統計資料。為什麼身為管理者看不到別人上傳的代碼,這不科學。
    scarky4.png
  • 放上博客有三種方式。
    scarky1.png

使用心得

  • 正如上方的題目,編輯頁面要打 HTML,這點不科學也不方便。
  • 頁面顯示上就是固定,大小無法更動。
  • 題目生存期限有多久?曾經放著一年前的題目還在。
  • HTML 打好放上去,編輯時從曾經打過的 <br/> 會消失。
  • 最後附上簡單的測試。
    <strong>題目描述</strong><br/><br/>
        <p>
            請將 NFA 轉換成 DFA,不用進行最佳化。
        </p><br/>
    <strong>輸入描述</strong><br/><br/>
        <p>
            輸入只會有一筆 NFA 描述,輸入以 EOF(end-of-file) 為結尾。
            <br/><br/>
            略 ...
        </p><br/>
    <strong>輸出格式</strong><br/><br/>
        <p>
        輸出對於每一組 DFA,格式如下。<br/>
        輸出第一行為字母集 CDFA (按照字典順序輸出)。<br/>
        <br/>
        略 ...
        </p><br/>
    <strong>Example Input :</strong><br/>
        <pre>
        (l,a,b,2)
        (2,0)(3,0)(0,0)
        (0,0)(4,5)(0,0)
        (0,0)(0,0)(4,0)
        (0,0)(5,0)(5,0)
        (*,*)(*,*)(*,*)
        略 ...
        </pre>
    <strong>Example Output:</strong><br/>
        <pre>
        (a,b)
        (1,2)(*3,4,5)(0)
        (*3,4,5)(*5)(*4,5)
        (*5)(0)(0)
        (*4,5)(*5)(*5)
        略 ...
        </pre>
    

Hexo

  • 文章格式
    title: Scarky 您的博客線上檢測系統
    date: 2014-04-17 19:35:27
    tags: [Scarky, ACM, Judge]
    categories: 出題解題
    scarky: PNFCQOY5
    
  • 文章顯示
    theme/layout/_partial/post/article.ejs
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <div id="main" class="<%= item.layout %>" itemscope itemprop="blogPost">
    <article itemprop="articleBody">
    <%- partial('header') %>
    <div class="article-content">
    <%- partial('gallery') %>
    <% if( table&&(item.toc !== false) && theme.toc.article){ %>
    <div id="toc" class="toc-article">
    <strong class="toc-title"><%= __('contents') %></strong>
    <%- toc(item.content) %>
    </div>
    <% } %>
    <% if(item.scarky) { %>
    <!-- scarky widget http://scarky.com/ -->
    <script type="text/javascript" src="http://scarky.com/widget/get/<%= item.scarky %>/"></script>
    <!-- end scarky widget -->
    <% } %>
    <%- item.content %>
    </div>
    <%- partial('footer') %>
    </article>
    <%- partial('pagination') %>
    <%- partial('comment') %>
    </div>
Read More +

作業系統 筆記 (1)

讀物

現在恐龍書不知道第幾版了,而且中文翻譯有點慘。看英文原文又太慢的情況,剛好查到聯合大學陳士杰教授寫的 ppt。繁體中文的說明,採用恐龍書第七版的內容。

下附章節簡報和課後習題解答。

稍微看過每一章的內容後,就可以著手看習題解答。

CH 1
CH 2
CH 3
CH 4
CH 5
CH 6
CH 7
CH 8
CH 9
CH 10

恐龍書課後習題解答 感謝大大的提供

之前也有好幾次參照教授寫的中文簡報,相當有助益。

可能遭遇的問題

個人拙見,請自行過濾

Round-Robin Scheduling

  • 這個問題在寫考題的時候,略顯著的疑惑。
  • 對於 Round-Robin Scheduling 的部分
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    queue Q
    while(true) {
    w = Q.front()
    w = work(w)
    if(hasProcess())
    Q.push(nextPorcess())
    if(w != null)
    Q.push(w)
    time++
    }
    詳見代碼後,由於超過時限後,還要將變數存起來,所以丟入 queue 的時間會晚一點,也就是說在同一時刻會慢於新抵達的 process。之後的程序就按照 queue 的順序去運行。

考古題(課本後習題)

(=゚ω゚)= 下附解答僅個人拙見,請勿隨意採信,請發揮您的善心,救救笨蛋

95 期中考

  • What is multiprogramming ? what is time-sharing ?(10%)

    • Multiprogramming(多重程式):

      • 定義:
        內存有多個 processs 同時執行,一般電腦的運行方式。透過 CPU scheduling 將發生中斷 (eg. wait for I/O complete, resource not available, etc.) 的行程切換給可執行的運作。
      • 特色:
        可以避免 CPU idle,提高 CPU utilization(使用率)
      • 其他:
        1. Multiprogramming Degree:系統內存在執行的 process 數目
        2. 通常 Multiprogramming Degree 越高,則 CPU utilization 越高(p.s. ch7 Thrashing 除外)
        3. 多個 process 同時執行,mode 有兩種 Concurrent(並行)、Parallel(平行)
    • Time-sharing:

      • 定義:
        Multiprogramming 的一種,在 CPU 排班法則方面,其使用 RR(Round-Robin) 法則。
        // RR 法則-CPU time quantum,若 process 在取得 CPU 後,未能於 quantum
        // 內完成工作,則必須被迫放棄 CPU,等待下一次輪迴。
      • 特色:
        對每個 user 皆是公平的,適用在 user interactive 且 response time (反應時間)要求較短的系統環境,透過 resource sharing 技術(eg. CPU scheduling, memory sharing, spooling 達到 I/O Device 共享),使得每個user皆認為有專屬的系統存在。
  • Describe the differences between symmetric and asymmetric multiprocessing. What are three advantages and one disadvantage of multiprocessor systems ?
    In Distributed System - Multiprocessor - Tightly-Coupled System(different from Loosely-Coupled Distributed System)

    • Symmetric Multiprocessors (SMP) 對稱式多處理器
      • 定義:
        每個 processor 的能力皆相同,即可負責的功能完全一樣。萬一某個 processor 壞了,其上工作可由其他processor 接手,系統不會整個 crash,只是整體效能下降而已。
      • 特色:
        Reliability (可靠性)大幅提升,強調 load balancing (負載平衡)(每個CPU的工作負擔相同)
    • Asymmetric Multiprocessors (ASMP) 非對稱式多處理器
      • 定義:
        不同(群)顆的 processor,其負擔的功能不盡相同,在此架構下,通常含有一個Master CPU,負責工作的分派與協調,其他 CPUs 稱為 Slave CPU (稱為 Master-Slave Architecture)
      • 特色:
        效能通常較SMP高,但可靠度較差
  • What are the differences between a trap and an interrupt? What is the use of each function ?
    • Trap:
      軟體產生 system call
      an exception in a user process.
      ex. system call (software divide-by-zero)
    • Interrupt:
      硬體產生 signal
      something generated by the hardware.
      ex. IO-complete interrupt (hardware generated)
    • 兩者相同之處
      從 User Mode 切換到 Kernel Mode。
      兩者都算是 interrupt 中斷指令。
  • What is the purpose of system calls?
    System calls allow user-level processes to request services of the operating system.
    System calls 提供 使用者級別 的程序來請求作業系統給的服務。
    // process control, file Management, device management, information maintenance, communication
  • Describe the differences among short-term, medium-term, and long-term scheduling.
    • short-term (CPU scheduler) —
      CPU 工作排程
      selects from jobs in memory those jobs that are ready to execute and allocates the CPU to them.
    • medium-term —
      常用於分時系統的排程器。當記憶體不夠的時候,需要暫時將部分的執行程序搬出,將新來的程序載入,置換機制被建置用來移除部份在記憶體執行中及恢復那些被暫時移除的程式。
      used especially with time-sharing systems as an intermediate scheduling level. A swapping scheme is implemented to remove partially run programs from memory and reinstate them later to continue where they left off.
    • long-term (job scheduler) —
      將 job 變成 process 的工作排程,將工作從硬碟載入到主記憶體中。
      determines which jobs are brought into memory for processing.
  • Can a multithreaded solution using multiple user-level threads achieve better performance on a multiprocessor system than on a single-processor system? Why?
    • A multithreaded system comprising of multiple user-level threads cannot make use of the different processors in a multiprocessor system simultaneously. The operating system sees only a single process and will not schedule the different threads of the process on separate processors. Consequently, there is no performance benefit associated with executing multiple user-level threads on a multiprocessor system.
    • 以 user-level hreads 實現 multithread 的程式,在多處理器系統中不能比在單處理機系統中有更好的效率, 因在多處理機系統中之作業系統不會將多個 CPU 同時分配給該 user-level multithread 程式。
  • Consider the following set of processes, with the length of the CPU-burst time given in milliseconds:

    Process           Burst Time         Priority
      P1                 10                  3
      P2                  1                  1
      P3                  2                  3
      P4                  1                  4
      P5                  5                  2
    

    The processes are assumed to have arrived in the order P1,P2,P3,P4,P5, all at time 0.

    • (a) Draw four Gantt charts illustrating the execution of these processes using FCFS, SJF, a nonpreempitive priority(a small priority number implies a higher priority), and RR(quantum = 1) scheduling.(5%)
    • (b) What is the turnaround time of each process for each of the scheduling algorithms in part(a).(5%)
    • (c) What is the waiting time of each process for each of the scheduling algorithms in part(a).(5%)
    • (d) Which of the schedules in part (a) results in the minimal average waiting time(over all processes)? (5%)

      請參照上附的習題解法。
      

      5.12 solution


96 期中考

  • FCFS, SJF, Priority, Round-Robin and Multilevel Queue
    Which can be preemptive ? (5%)

    • preemptive 可搶先
      SRTF (剩餘最短優先)、Priority (優先權優先)、Multilevel Queue (多層佇列)、RR
    • non-preemptive 不可搶先
      FCFS (先到先服務)、SJF (最短工作優先)、Priority (優先權優先)
    • Priority (優先權優先) 屬於可搶先跟不可搶先。
    • 可搶先的定義為非自願性被踢出 CPU。
  • What are the four main purposes of an operating system ? (10%)

    • Managing programs
    • Managing Memory
    • Handling input and output
    • User Interface
  • Please give a detail description on the differences among the terms multiprocessing, multitasking and multithreading. (15%)

    • multiprocessing
      具有多個處理器,在同一時間可以在各自處理器上運行程序。
    • multitasking
      執行單一使用者的多個行程,利用排程器讓每一個行程都在平均時間內解決。
    • multithreading
      可以將程序切成好幾個執行緒,若硬體可以同時執行多個執行緒,效率將會上升,如果不能,由於速度夠快看起來也很像多個執行緒同時運行。
  • What are the differences between a trap and an interrupt ? What is the use if each function ? (20%)

    • Trap:
      軟體產生 system call
      an exception in a user process.
      ex. system call (software divide-by-zero)
    • Interrupt:
      硬體產生 signal
      something generated by the hardware.
      ex. IO-complete interrupt (hardware generated)
    • 兩者相同之處
      從 User Mode 切換到 Kernel Mode。
      兩者都算是 interrupt 中斷指令。
  • What is the purpose of system calls, Please describe three general methods that be used to pass parameters to the operating system. (10%).

    • System call 由作業系統提供 API interface 給 user program,可以藉由 system call 向作業系統請求服務,作業系統接收到請求後,執行完報告結果給 user program。
    • [方法1] Registers
      利用Registers ( 暫存器 )儲存這些參數
      優:速度快
      (∵不用作記憶體的存取 )
      缺:不適用於參數個數多的情況
    • [方法2] Memory
      將參數利用 Table 或 Block 的方式儲存在 Memory 中,同時利用一個 Register 記錄此 Table 或 Block 的起始位址,並傳給O.S.
      優:適用於參數個數較多的情況
      缺:速度慢
    • [方法3] Stack
      利用System Stack (堆疊 )。要存放參數時,將之Push 到Stack Stack, 再由O.S.從Stack中Pop 取出參數 。
      Stack在系統中比Register多一些(可用Mem. 或其它硬體(如:Register)來實作此Stack)
  • What is a process ? Draw the diagram of Process State. And describe every state. (15%)
    process state

  • What are the differences between thread and process ? Why do threads have much shorter context switching times ? (10%)

    |        Thread                   |      Process              |
    |---------------------------------|---------------------------|
    | Light Weight Process            | Heavy Weight Process      |
    |                                 |                           |
    | 同一個Task (或 Process ) 內的   |  不同的Process之間無共享的| 
    | Threads可以共享 Code Section,   |  Address Space,互為獨立。|
    | Data Section, 及O.S. Resources  |                           |
    |                                 |
    | Context Switching 負擔輕        |  負擔重
    |                                 |
    | Thread的管理(Management)成本低  |  成本高
    | (管理項目: Creation,           |
    | Scheduling, Context, Switching  |
    | Switching…etc.)                 |
    |                                 |
    | 一個Task內有多條Threads存在     |  一個Task內只有一條Thread
    |  Process (Task) 內的某 Thread   |
    | 被 Block,則可切到其它Thread    |
    | 執行。此時,若 Process 內只要還有
    | Thread 在執行,則 Process 不會被 Block
    
  • What is Multilevel Feedback-Queue scheduling ? (5%)

    定義:
    與Multilevel Queue的定義相似,差別在於允許 Process 在各佇列之間移動 ,以避免Starvation 的情況。
    * 採取類似 “Aging” 技術,毎隔一段時間就將 Process 往上提升到上一層 Queue 中。∴在經過有限時間後,在 Lower Priority Queue 中的 Process 會被置於 Highest Priority Queue 中。故無 Starvation。
    * 亦可配合降級之動作。當上層 Queue 中的 Process 取得 CPU 後,若未能在 Quantum 內完成工作,則此 Process 在放棄 CPU 後,會被置於較下層的 Queue 中。
    
  • Please draw the Gantt charts for the following processes for the problems shown below.
    (a) Round-Robinm time quantum = 1 (5%)
    (b) Shortest-remaining-time-first (Preemptive SJF) (5%)

                Arrival Time    Brust Time
    
        P1      0               4
        P2      1               2
        P3      2               3
        P4      5               4
        P5      6               3
    
    (a) Time : 0
        Queue: P1
    
        0   1
        +---+
          P1
    
        先丟入 P2, P1 因為超時丟入,此時執行 P2
        Time : 1
        Queue: P2, P1
    
        0   1   2
        +---+---+
         P1  P2
    
        丟入 P3, P2 因為超時丟入,此時執行 P1
        Time : 2
        Queue: P1, P3, P2
    
        0   1   2   3
        +---+---+---+
         P1  P2  P1
    
        P1 因為超時丟入,此時執行 P3
        Time : 3
        Queue: P3, P2, P1
    
        0   1   2   3   4
        +---+---+---+---+
         P1  P2  P1  P3
    
        P3 因為超時丟入,此時執行 P2
        Time : 4
        Queue: P2, P1, P3
    
        0   1   2   3   4   5
        +---+---+---+---+---+
         P1  P2  P1  P3  P2
    
        P2 完成,P4 抵達丟入,此時執行 P1
        Time : 5
        Queue: P1, P3, P4
    
        0   1   2   3   4   5   6
        +---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1
    
        P5 抵達丟入,P1 超時丟入,此時執行 P3
        Time : 6
        Queue: P3, P4, P5, P1
    
        0   1   2   3   4   5   6   7
        +---+---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1  P3
    
        P3 超時丟入,此時執行 P4
        Time : 7
        Queue: P4, P5, P1, P3
    
        0   1   2   3   4   5   6   7   8
        +---+---+---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1  P3  P4
    
        P4 超時丟入,此時執行 P5
        Time : 8
        Queue: P5, P1, P3, P4
    
        0   1   2   3   4   5   6   7   8   9
        +---+---+---+---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1  P3  P4  P5
    
        P5 超時丟入,此時執行 P1
        Time : 6
        Queue: P1, P3, P4, P5
    
        0   1   2   3   4   5   6   7   8   9  10
        +---+---+---+---+---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1  P3  P4  P5  P1
    
        P1 完成,此時執行 P3
        Time : 10
        Queue: P3, P4, P5
    
        0   1   2   3   4   5   6   7   8   9  10  11
        +---+---+---+---+---+---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1  P3  P4  P5  P1  P3
    
        P3 完成,此時執行 P4
        Time : 11
        Queue: P4, P5
    
        0   1   2   3   4   5   6   7   8   9  10  11  12
        +---+---+---+---+---+---+---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1  P3  P4  P5  P1  P3  P4
    
        ...
    
        0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
         P1  P2  P1  P3  P2  P1  P3  P4  P5  P1  P3  P4  P5  P4  P5  P4
    

課本習題快取區

ch 5

  • 5.9 Why is it important for the scheduler to distinguish I/O-bound programs
    from CPU-bound programs?
    為什麼排程器需要需分 IO 密集程式 CPU 綁定程式 ?

Answer: I/O-bound programs have the property of performing only a small amount of computation before performing I/O. Such programs typically do not use up their entire CPU quantum. CPU-bound programs, on the other hand, use their entire quantum without performing any blocking I/O operations. Consequently, one could make better use of the computer’s resouces by giving higher priority to I/O-bound programs and allow them to execute ahead of the CPU-bound programs.
IO 密集程式占用 CPU 的時間比較少,大部分時間等在等待 IO。相反地 CPU 綁定程式則會大幅度占用 CPU 的時候,因為沒有 IO 操作的堵塞。

而 CPU bound 的程序因此而得到了很多調度機會並且每次都能把CPU run完。故在這樣的系統裡要給 I/O bound 的程序更高的優先級使其能被調度得更多些。

  • 5.10 Discuss how the following pairs of scheduling criteria conflict in certain
    settings.
    a. CPU utilization and response time // CPU 使用率 和 回應時間 的比較
    b. Average turnaround time and maximum waiting time // 平均運轉時間 和 最大等待時間 的比較
    c. I/O device utilization and CPU utilization // IO 裝置使用率 和 CPU 使用率 的比較

Answer:
a. CPU utilization and response time: CPU utilization is increased if the overheads associatedwith context switching isminimized. The context switching overheads could be lowered by performing context switches infrequently. This could, however, result in increasing
the response time for processes.
CPU 的使用率(utilization)上升時,切換工作的次數(context-switches)就會少,由於切換次數少,則回應時間(response time)就會上升。

b. Average turnaround time and maximum waiting time: Average turnaround time is minimized by executing the shortest tasks first. Such a scheduling policy could, however, starve long-running tasks and thereby increase their waiting time.
平均運作時間(average turnaround time) 的最小化可以藉由最短工作優先的方式,但是這將會使得長工作飢餓,如此會增加最大等待時間。

c. I/O device utilization and CPU utilization: CPU utilization is maximized by running long-running CPU-bound tasks without performing context switches. I/O device utilization is maximized by scheduling I/O-bound jobs as soon as they become ready to run, thereby incurring the overheads of context switches.
CPU 使用率的上升盡可能讓 CPU 密集工作長時間運行 (減少 IO 或者其他的中斷所引發的上下文切換),IO 裝置使用率的上升靠的是讓排入的 IO 密集工作立即地運行,但這會增加上下文切換的開銷。

  • 5.11 Consider the exponential average formula used to predict the length of the next CPU burst.What are the implications of assigning the following values to the parameters used by the algorithm?
    使用指數平均公式去預測下一次的 CPU burst。 t0 預估時間。
    a. a = 0 and t0 = 100 milliseconds
    b. a = 0.99 and t0 = 10 milliseconds

Answer: When a = 0 and t0 = 100 milliseconds, the formula always makes a prediction of 100 milliseconds for the next CPU burst. When a = 0.99 and t0 = 10 milliseconds, themost recent behavior of the process is given much higher weight than the past history associated with the process. Consequently, the scheduling algorithm is almost memoryless, and simply predicts the length of the previous burst for the next quantum of CPU execution.
當 a = 0 時,預測的時間總會是 100 milliseconds,而當 a = 0.99 時,將會高度依賴近期幾次的結果,而對於歷史關聯只有較輕的權重。
// t(n+1) = a * 上一次實際時間 + (1 - a) * t(n)

Reference

Kernel Mode 與 User Mode 的概念
恐龍書中文 ppt 介紹 聯合大學 陳士杰

Read More +

Nodejs 初學上手

網站利器

簡介

寫網站對筆者來說是第一次,只有看過別人用 PHP framework 架站,會用到 SQL 語法,還要搭配前端的 CSS、javascript,到現在 javascript 和 CSS 都仍不熟,那這麼還寫一篇文章出來害人呢。

Nodejs 出來後,一個完全 javascript 的環境,撇開了 Apache,只剩下 Javascript 和前端頁面!

前置作業

您需要會點,倒不如說吾就這點程度。

  • HTML 基礎文本語法,能夠造出靜態網頁。
  • Javascript

環境安裝

  • 安裝 NodeJs
  • 安裝 MongoDB
  • 安裝 WebMatrix
    非必要,但是開專案後大體上就會棄,用 Sublime 編輯。其實是因為到了 express 網站,也看不懂要去哪裡下什麼指令指令去安裝架設。

目標

知道 Nodejs 在做什麼,並且用它來寫網站。

歷程

一開始被丟了相當大的問題,原因是當下根本不清楚 Nodejs 是什麼,於是小夥伴們先丟了一個 七天學會 Nodejs 的鏈結給我。

就一股腦地走馬看花,同時也看了很多篇相關於 Nodejs 的文章,但仍壓根不知其何物,只有見識到相當多的指令說明,果然還真必須實作一番才能理解。

慧根嚴重不足,請多多見諒

以前可能用過 Apache,但也不知道其功能,只知道可以幫助將資料藉由 port 80 傳出去,而且還因為某個軟件自帶的安裝 Apache ,其中漏洞導致成為殭屍網路的一群發動攻擊。那件往事還真是難忘,在宿舍還被鎖網。

Nodejs 相當強,全部基於 javascript 可以運行讀檔寫檔還有架站,php 的功能全都包了,但是對於 SQL 資料庫的部分,由於 Nodejs 的操作插件都是在 NPM 平台上,有什麼需求都必須去那邊下載使用。大多數使用 Nodejs 搭配 mongoDB,就相當於 php 搭配 MySQL。

因此藉由上述內容,請明白 Nodejs 和 NPM 是同時灌的,就像 java application 必須有 import library 使用。

換了語言換了腦袋,真的只認為是換語言如此單純的事情嗎?

對於架站 framework 來說,應該不少有人用過 php framework,如果不明白 framework 也沒關係,現在動手去查。看完之後再去查查 MVC MVP MVVM。總之,如果在大學寫過一點程式,多少都會明白自幹框架是多麻煩的事情,但也是好修好改的開始。這裡不談 php framework,nodejs 有一個 express 的 framework,基於我的無知,看不懂官方網站如何指導安裝,那使用邪惡 Windows WebMatrix 提供的網頁開發方式,先快速開啟專案。

後來是明白 express 的安裝方式,express github 上的 README.md 說得相當清楚,這時也要培養看完 README.md 再行動的習慣。

打開 express 專案,一定會發現有數個未知附檔名的出現,大多是 .jade,不要太擔心, jade 檔案就是 html 基於縮排而成的語言,相當精簡且可以根據 express 架構導入變數值。

如果要為這個專案下的 server.js (舊版命名為 app.js) 增加新的模組套用怎麼做?

yourProject/folder/
1
$ npm link modulesName

如果原本使用下述安裝至作業系統,則在 server.js 則不會發生找不到模組的問題。

anywhere
1
$ npm install -g modulesName

接著你會發現專案下 node_modules 會有無數你在 server.js 中 require 的模組內容,同時也會發現模組下又有相依模組,可以層層查閱,這是一個很有趣的現象,不知道模組與模組下會不會有相同相依模組存在。看起來可以猜測為-有。

專案都開啟了,最關注於 CSS 和 JQuery 怎麼灌輸進去。

project/views/layout.jade
1
2
3
4
5
6
7
8
9
10
11
12
doctype 5
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
link(rel='stylesheet', href='/stylesheets/ui-darkness/jquery-ui-1.10.4.custom.css')
link(rel='stylesheet', href='/stylesheets/webstyle.css')
script(src='/javascripts/jquery-1.10.2.js')
script(src='/javascripts/jquery-ui-1.10.4.custom.js')
body
block content
<script src='/javascripts/global.js'></script>

而你的 javascript file 就在 project/public/javascript 下,而 CSS 則在 project*public/stylesheets 下,頓時心中一塊大石頭放下了,在還沒調用資料庫前,至少靜態網頁能在 express 運行中出現。

先談到這裡了,要用 express 架出完整的網站,還要走段 mongoDB 的運用,還要學會 jade 的撰寫方式。

其實學到 nodejs express 後,第一個挖到的是 Hexo blog 的製作,也就是你眼前所見的網站。這是一個基於 nodejs 下的套件,使用 markdown 編撰文章,雖然沒有文章線上編輯,幾乎靠者純文字檔的方式運行,為了架設這個頁面,費盡了一番苦心想要進行搬家工程。

如何進行搬家工程? 爬蟲 對吧?那要用什麼語言進行爬蟲,沒錯!就是剛學到的 Nodejs,可是要轉換成 markdown file 耶,之後是失敗了,因為有很多 CSS 上的問題,轉換一直不理想。

如何架出第一個有 ajax 和 database 的 express 網站,可以查閱下方鏈結。

Resource & Reference

Read More +

大學專題紀錄 Universities Project

Morris’ 大學專題

前言

大學專題時間為期一年,分為上下兩學期習滿才能畢業,但有些科系不是,但多少資工系基本上都是的,沒有修過專題,就相當於只是寫學校作業!如何研究與邁向下新的目標,這將會是專題給您的經驗。

怎麼選專題教授

首先,先來區分教授類型。

  • 自由放任型
    您的專題將會任您發展,同時也是掛名的教授,相當建議有想法的同學們去選,畢竟想做想學的事情可能很多,中間變卦也是常有的事情,但您必須真的有去學到知識的衝勁。但有自主學習動力的人少之又少,更別說學習目標的定論,如果您是那種不管課業上什麼,都會額外深入學習者 … 或許您有那股潛力。
  • 學術研究型
    您將會開始看論文,並且實作和學習。身邊人沒什麼聽聞。
  • 產學合作型
    您將會用基礎程式和教授專長去討論做出相關產品,至於有沒有深入了解產業需求和教授專長領域又是另一回事情了。這是最有可能產出作品的,如果想要在面試中講講大學做了什麼成果,大概這是最有機會的一群。
    但是必須得明白,有作品不見得是好事,也就是說沒有實質學習和產出品質,也只是陡增垃圾。
  • 業界指導型
    相較於產學合作,告訴您宏觀的慘業現況,並且指導走入業界環境,突破學習的局限與個人思維,通常是屬於資訊系所中偏向軟體開發教授們的領導風格。

選教授要看個人性格,如果平常不怎麼專注於學習者,就跟著最要好的小夥伴們選吧。

而雖然對於 ACM 算法競程稍有經驗,可能就會被旁人認為要去玩學術研究,不過學術研究也是相當嚴苛的一條路,沒有想法沒有產出,那可是會逼死人的,只有一年的學習專題(當然有人會無限延長),最後選了軟體工程來玩玩,結果沒想到跟以前所寫的 ACM 那套可說是八字相剋。

於是漫長的旅行就開始了 …

何時修專題課程

專題要不要產出

很多人一直都想要有個成果發表展之類的,或者是可以張貼海報展覽的機會,看起來會留下美好的紀錄,且認為相當有機會在面試的時候被提及,以免被問到時,什麼都沒有得說。

但是請自行思考,這是唯一的成果製造流程?

進度狀況

  • 上學期為軟體工程圍觀

    • 程式基礎-物件導向,軟工產業介紹

      只會寫學校作業是不夠的,產業界要的不是這種人。

    • 修習物件物件導向課程
      雖然以前修過物件導向,但是相當輕描淡寫,真正應該是要學到 Design pattern 、資料表單的建造後,才算學過物件導向,否則只是濫用三大利器繼承、多型、封裝。

      學過、學會、應用 乃屬三個階段,少自以為是。

    • 工具的重要性

      如何用好工具將會給予後期強大的助力開發。

    • 開發前奏曲 prototype 的製作與重要性
      與業界需求產出網頁 prototype,使用 JQuery, HTML。

      相當慘淡,經驗沒到,思維不足,無法造出需求結果。

  • 下學期為軟體工程入門

    • 跟著 Mozilla 導師們學習
      • Sprint meeting
      • GitHub
      • Nodejs
      • FirefoxOS - gaia // 環境卡太久,什麼都還沒學到就胎死腹中

階段性

學習條目

結語

Read More +

網站看板娘製作

簡介

仿製偽春菜,用於網站小幫手,或者象徵物般的存在,高階可以引入對話 AI。 原版偽春菜,常見的別名又稱伺か、何か、任意、さくら。是一種電腦的桌面程式。視其功能的不同,從站在那陪使用者聊聊天解解悶,或報時對時收郵件,甚至處理電腦中大大小小的事都有可能辦到 而網站移植版有許多版本,看到大部分為php 版本、以WordPress Blog插件為大宗。 移植版常有的功能縮減為顯示公告、賣萌、統計上站人數等。跟電腦版不同較少出現會隨互動顯著成長的類型,另外在技術層面上,很多牽扯到資料庫的運用,相當複雜。

在靜態頁面上,如何簡單運用外連資料庫就是本次課題,決定開始偷偷動手腳了。

對了,Jquery 的模組化單純是老尼克推坑,接著朝向 AI 系統發展,就以目前情況來看,可能沒有時間去完成或了解。但是有一個關鍵詞 AIML 網址內附程式,可能會幫助興趣者從零開始建造,如果要有中文可能要去調用翻譯機就是了。還是要說明一下,這裡偷偷用了 google 提供的服務,所以沒有完善的資料庫語法,算是邪門歪道。

製作開始

前置作業

  • 獲取自己的 Google Spreadsheet 的 key 和 formkey。
  • 建立方式
    • 製作 Google 表單,也就是問卷。
    • 放出一個選項命名為 ‘store_data_base’ (預設,否則您將要修改 json)
    • 之後您將會得到表單對應的試算表。
    • 分別找到 key 和 formkey 還有表單欄位的 html tag id.
      • key - 在相對的試算表中,查閱當前網址
        https://docs.google.com/spreadsheet/ccc?key=0ArRwmWo93u-mdG93a2dkSWxIbHEzZjRIeDdxZXdsU1E&usp=drive_web#gid=0
        
        key=後面一串便是您需要的,您可以檢查以上的值和代碼中的預設值。
      • formkey - 在您開啟問卷的網址中
        https://docs.google.com/forms/d/1xADUIiBq1ksH7lxwSch1Nz_p2gSxdJttmv5OJOxJye0/viewform
        
        會發現 d/formkey/viewform 就在其中。
      • html tag id - 對問卷頁面查閱原始碼,找到輸入欄位類似於 entry.2030600456 的格式。
  • 本站使用的 My Google Spreadsheet 如有表單建立疑慮可參考。

  • 以下代碼可能會與 GitHub 上不同,會盡可能去兩邊更新。

JQuery Code

jquery.morris.ukagaka.resource.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
(function($){ // 封裝起來, 以免和外界js 變數衝突到
$.fn.extend({
//plugin name - animatemenu // 定義 plugin 名稱
ukagaka: function(options) {
//Settings list and the default values // 設定plugin input parameters 的預設值
var defaults = {
googleKey: '0ArRwmWo93u-mdG93a2dkSWxIbHEzZjRIeDdxZXdsU1E',
googleFormkey: '1xADUIiBq1ksH7lxwSch1Nz_p2gSxdJttmv5OJOxJye0',
googleSheet: "od6",
googleSheetField: "entry.2030600456",
talkTime: 10000
};
// 把預設值和實際輸入值比對, 如果有傳入值的則以傳入值為主
// 如此便得到輸入值 options (在此匿名函式中存在之變數)
var options = $.extend(defaults, options);
// 執行此 plugin 的實際動作, 對其作用對象的陣列迭代(iterate over), 例如說對$(".class_name") 呼叫此plugin, 則 this.each 就代表所有帶有 class_name 為 class 屬性的DOM element
return this.each(function() {
var o = options;
//Assign current element to variable, in this case is UL element
var obj = $(this); // obj 代表迭代到的單一物件
var key = o.googleKey;
var sheet = o.googleSheet;
var formkey = o.googleFormkey;
var sheetfield = o.googleSheetField;
var talking = [];
var innerSettingHTML = "";
innerSettingHTML += "<div id='ukagaka_img'></div>";
innerSettingHTML += "<div class='ukagaka_box'>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_msgbox'>汝 先看看周遭</div>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_menubox' style='display:none'>使用選單功能&#65292;吾才不需要汝教。<br/><br/><span id='ukagaka_menu_btn_addstring'>$ 學習</span><span id='ukagaka_menu_btn_renewlist'>$ 日誌</span><span id='ukagaka_menu_btn_exit'>$ 結束</span></div>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_stringinput' style='display:none'>請輸入讓偽春菜學的句子<br/><br/><input id='ukagaka_addstring' type='text'/><span id='ukagaka_addmenu_add'>$ 增加</span><span id='ukagaka_btn_menu'>$ 取消</span></div>";
innerSettingHTML += "<div class='ukagaka_msg' id='ukagaka_renewlist' style='display:none'>更新日誌<br/><br/>Morris 修正<br/><br/>找尋 AI 系統<br/>找尋 AI 對話<br/><br/><span id='ukagaka_btn_menu'>$ 取消</span></div>";
innerSettingHTML += "<input id='ukagaka_sheetfield' type='hidden' value='" + sheetfield + "'>";
innerSettingHTML += "</div>";
obj.html(innerSettingHTML);
var footerMenuHTML = "";
footerMenuHTML += "<div id='ukagaka_controlpanel'>";
footerMenuHTML += "<span id='ukagaka_btn_display'>Display</span> ";
footerMenuHTML += "<span id='ukagaka_btn_menu'>Menu</span>";
footerMenuHTML += "</div>";
obj.after(footerMenuHTML);
function reloadtalking(){
/* JSON / load string from database */
$.getJSON("https://spreadsheets.google.com/feeds/list/" + key + "/" + sheet + "/public/values?alt=json", function(JData){
for (var i = 0; i < JData.feed.entry.length; i++) {
talking[i] = JData.feed.entry[i].gsx$storedatabase.$t;
// console.log("talk stmt : " + talking[i]);
}
$('input#ukagaka_addstring').attr('placeholder', '目前春菜學會了' + JData.feed.entry.length + '個字彙');
});
};
$(window).load(function(){
var talk_timer = setInterval(talkingbox, o.talkTime);
function talkingbox() {
if($("#ukagaka_msgbox").css("display") != 'none')
$("#ukagaka_msgbox").fadeOut(500, function(){
$(this).html(talking[Math.floor(Math.random() * talking.length)]).fadeIn(500)});
}
});
reloadtalking();
obj.draggable();
$(document).on('click', "span#ukagaka_btn_display", function(event) {
$("#ukagaka_panel").fadeToggle(1000);
});
$(document).on('click', "span#ukagaka_menu_btn_exit", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_msgbox").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_btn_menu", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_menubox").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_menu_btn_addstring", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_stringinput").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_menu_btn_renewlist", function(event) {
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_renewlist").delay(500).fadeIn(500);
});
$(document).on('click',"span#ukagaka_addmenu_add", function(event) {
var add = $("input#ukagaka_addstring").val();
var googleSheetField = $('input#ukagaka_sheetfield').val();
var sendData = {};
sendData[googleSheetField] = add;
if(!((add.length <= 1) || add.indexOf('script') > -1|| add.indexOf('body') > -1 ||
add.indexOf('style') > -1 || add.indexOf('link') > -1 || add.indexOf('iframe') > -1 || add.indexOf('head') > -1 ||
add.indexOf('nav')>-1||add.indexOf('object')>-1||add.indexOf('embed')>-1)){
$.ajax({
type: 'POST',
url: 'https://docs.google.com/forms/d/' + formkey + '/formResponse',
data: sendData,
dataType: "xml",
statusCode: {
0: function() {
$("input#ukagaka_addstring").attr("value","");
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_msgbox").fadeOut(500, function(){
$(this).html("偽春菜學習了 !").fadeIn(1000)});
},
200: function() {
$("input#ukagaka_addstring").attr("value","");
$(".ukagaka_box div").fadeOut(500);
$("#ukagaka_msgbox").fadeOut(500, function(){
$(this).html("偽春菜學習了 !").fadeIn(1000)});
}
}
});
} else {
alert("OOPS!偽春菜不接受這個字串喔!");
}
});
});
}
});
})(jQuery);

CSS

以下 CSS 為原作設定。

ukagaka.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
62
63
64
65
66
67
68
69
70
71
72
73
74
#ukagaka_controlpanel {
background:white;padding:8px;
box-shadow:#555 0px 0px 4px;
text-shadow: #555 0px 0px 1px;
margin-bottom:-3px;
border-radius:5px 5px 0 0;
position:fixed;
right:40px;
bottom:0px;
font-size:10pt;
z-index:101;
}
#ukagaka_controlpanel span, #ukagaka_panel span {
padding:5px;
cursor:pointer;
height:0px;
}
#ukagaka_panel {
position: fixed;
right: 10px;
bottom: 10px;
width: 88.2px;
height: 230.3px;
z-index:10;
}
/* ukagaka msgbox */
.ukagaka_box{
position: absolute;
bottom: 117px;
right: 97px;
font-size: 10pt;
}
.ukagaka_msg{
width:195px;
background: white;
padding:10px;
word-wrap: break-word;
word-break: normal;
color:black;
box-shadow:rgba(15,15,15,0.8) 0px 0px 8px;
}
.ukagaka_msg::after {
width:10px;
height:10px;
-moz-transform:rotate(45deg);
-webkit-transform:rotate(45deg);
-o-transform:rotate(45deg);
-ms-transform:rotate(45deg);
transform:rotate(45deg);
background:white;
content: '';
float: right;
margin-right: -14px;
margin-top:7px;
box-shadow:rgba(15,15,15,0.8) 3px -3px 8px -3px;
}
/* */
#ukagaka_img {
background: url(./img/ukagaka_img.png) no-repeat;
width: 126px;
height: 329px;
transform: scale(0.7);
-ms-transform: scale(0.7);
-webkit-transform: scale(0.7);
-o-transform: scale(0.7);
-moz-transform: scale(0.7);
position: absolute;
top: -49px;
right: -19px;
}
#ukagaka_stringinput input {
width:95%;
}

Stylus

  • 如果你在 Nodejs 下想使用,這裡提供本站使用的 ukagaka.styl。
  • 最後在 theme/xxxx/source/css/style.styl 進行匯入。
    1
    @import '_partial/ukagaka'
theme/xxxx/source/css/_partial/ukagaka.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#ukagaka_controlpanel
font-size 1.1em
padding 0 0 0.3125em 0
position fixed
right 40px
bottom 0px
background color-section
span
font-family font-custom-family
color color-blue
border-radius 10px
border-width 5px
border-style solid solid solid
&:hover
color color-theme2
transition color .5s
#ukagaka_panel
padding 0.5em 2% 1em
width 88.2px
height 230.3px
position fixed
right 40px
bottom 40px
span
padding 5px
cursor pointer
height 0px
.ukagaka_box
border-radius 10px
border-width 5px
border-style solid dashed dashed
position absolute
bottom 150px
right 120px
font-size 100%
background color-section
color gray
.ukagaka_msg
border-radius 10px
padding 0.5em 2% 1em
color color-white
width 195px
font-family font-custom-family, font-default
&::before
font-smoothing()
padding-right 0.5em
span#ukagaka_menu_btn_addstring, span#ukagaka_menu_btn_renewlist,
span#ukagaka_menu_btn_exit
border-radius 5px
border-width 1px
border-style solid solid solid
display inline
color color-blue
&:hover
color color-theme2
&::before
font-smoothing()
padding-right 0.5em
span#ukagaka_btn_menu, span#ukagaka_addmenu_add
border-radius 5px
border-width 1px
border-style solid solid solid
display inline
color color-blue
&:hover
color color-theme2
&::before
font-smoothing()
padding-right 0.5em
#ukagaka_img
background url(/img/ukagaka_img.png) no-repeat
width 150px
height 350px
transform scale(0.7)
-ms-transform scale(0.7)
-webkit-transform: scale(0.7)
-o-transform scale(0.7)
-moz-transform scale(0.7)
position absolute
top -49px
right -19px
#ukagaka_stringinput
>input
width 95%

如何使用 How to use

一般網頁

  • 記得要使用 utf-8 的網頁,否則中文將會炸掉。
  • 記的要使用 jquery-ui.js。
  • 記得要使用 jquery-x.x.x.js。
  • 最後引入咱們的 ukagaka.resource.js 和 ukagaka.css。
  • 然後與一般的 jquery 綁定相同,請參考以下代碼。
  • 如果您要客製化,請傳入 $(element).ukagaka(options);
  • options 的操作,請詳見 $(element).ukagaka({xxx:yyy, zzz:www});
main.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script src='jquery.morris.ukagaka.resource.js' type='text/javascript'></script>
<link type="text/css" rel="stylesheet" href="ukagaka.css">
<!-- ukagaka start -->
<script>
$(document).ready(function() {
$('#ukagaka_panel').ukagaka();
});
</script>
<div id='ukagaka_panel'>
</div>
<!-- ukagaka end -->
</body>
</html>

Hexo Blog

萬里花

  • 如果您希望每一頁都能見到
    • 在 footer.ejs 下插入 HTML TAG 代碼。
    • 在 after_footer.ejs 進行綁定
  • 反之,請自行摸索
theme/xxxx/layout/_partial/post/after_footer.ejs
1
2
3
4
5
6
7
<% if (config.ukagaka) { %>
<script src="<%- config.root %>js/jquery-ui.js"></script>
<script src="<%- config.root %>js/jquery.morris.ukagaka.resource.js"></script>
<script type="text/javascript">
$('#ukagaka_panel').ukagaka();
</script>
<% } %>
  • 插入位置看您的造化
theme/xxxx/layout/_partial/post/footer.ejs
1
2
3
4
5
<!-- ukagaka BEGIN -->
<div id='ukagaka_panel'>
</div>
<!-- ukagaka END -->

學習與撰寫過程

第一次寫 JQuery 和 Google Spreadsheet 相關,然後將 CSS 修改成 Stylus。

  • Stylus 是 CSS 的前置處理,有點類似 .cpp 產出 .exe 的關係。
  • 改寫時一堆問題,Stylus 默認縮排 2 個空白,編譯上一堆問題沒發現,導致浪費時間。
  • Google Spreadsheet 由於現在比較新版,每個表單的輸入欄位 id 也有所不同,所以可能會比較特別一點。
  • 什麼是靜態網頁的定義越來越模糊,javascript 帶你引入一堆外部資料庫,用低廉免錢重新審視。
  • 學習用 ajax 調用 Google Spreadsheet 資料。
  • Track code 能力訓練。

GitHub

Reference

Read More +

計算型智慧 - 學習 (Computational Intelligence)

計算型智慧

文章簡介

  • 下學期修了這門課,這其中會與另一門類神經網路有關。
  • 中間穿插工數和微積分的一些數學名詞。
  • 接著,您將會看到一系列筆者對計算型智慧的認知。
  • 看到以下內容,雖有數學模型、演算法成份,但主體為模擬自然界的各種思維。

算法設計

特定型最佳化法則

根據函數的特性,衍伸出來的搜尋方式,目標函數有特別性質,例如:線性、微分 … 等。微分法、梯度法都是屬於此類。再講白一點,一般大學時學的演算法都是如此,通常是具有最佳化結構的情況,因此會有最短路徑算法、二分搜尋、三分搜尋 … 等。

廣義型最佳化法則

不管目標函數的特性為何,無須修改設計法則,亂做一通、隨機搜索、以及接下來講的主題都屬此類。

模糊系統

模型簡介

  • 一般程式撰寫判斷條件相當精準,同時也不好做修正,畢竟一般人看不懂那麼多 if-else 語句。
  • 那有沒有更好一點的描述方式?這就是接下來要講的。
  • 如果硬要說明,模糊系統相當於一個精準輸入→亂來一通→精準輸出,也就是多了中間那個過程。

模型介紹

  • 是或不是,僅有 0/1 描述。
    真實世界是按照是的相似度有多高,不是的話就是有多高。或者描述多是有多多,少是有多少。

  • 歸屬函數 (membership function)
    值介於 [0, 1] 同時也是相似度的描述。
    詳細請參照 wiki 模糊集

  • 模糊關係 (fuzzy relation)
    簡單的說,一般用稀疏矩陣是用 N * N 的陣列,並且裡面存放 0/1 數值,但是在模糊關係中,將會使用 [0, 1] 之間的實數來代替。
    詳細請參照 wiki 模糊關係

    • 有什麼樣的操作 ?
      對於關係運算,也有關係合成或者是條件機率。對於關係合成就可以自訂函數來合成,而條件機率通常會使用積分去查閱,但是模糊關係至少三維空間 (因為多一個歸屬函數值),所以必須走投影擴充的方式,當然可能有其他的做法。
  • 單一規則,單一變數
    if x = p, then y = q.
    模糊起來

    x = p 的關聯性多少,y = q 的多少比率。
    

    舉個例子來說

    x 相當靠近 p, 假使說相似度 50%, 則 y = 0.5 * q
    

    以上是函數是說法,當然您可以自由選擇越接近反而越低,或者是客製化。

  • 單一規則,多變數
    if x1 = p1 and x2 = p2, then y = q

    • 由上一條,會有一點想法,那把兩個相似度取最小值如何?或者是相乘(假使相似度小於 1)。
    • 模糊沒有標準答案,覺得合理就行。
  • 單一規則,多變數
    if x1 = p1 or x2 = p2, then y = q

    • 由上一條,會有一點想法,那把兩個相似度取最大值如何?或者是相加後約束小於 1。
    • 模糊沒有標準答案,覺得合理就行。
  • 多規則,單一變數
    if x1 = p1, then y1 = q1
    if x2 = p2, then y1 = q2

    • 再藉由上一條相乘,那接著相加如何?還是要來個加權平均?
    • 一樣沒有標準答案,加權就是拿相似度出來當權重。
  • 多規則,多變數
    想必已經自動推論出來,在此就不多說。

  • 怎麼來亂?(隨便說說)

    • 函數式:多少相似度 p 根據多項式 f(p) 產出 y 值。
    • 語意式:畫出 f(y) = p 的圖,計算 p 所占有面積的面積(劃一條線取交集),來決定 y 要取多少。
    • 中間要不要遵守遞移律、交換律、結合律?照理來講是要的。
      不過想吐槽的是,都這麼模糊了,還要遵守這三律嗎?
      
  • 建造模糊規則

    • 通常由有經驗的專家口頭描述,然後讓程式慢慢演化。
    • 如果沒有專家可問,先把參數空間做切割,分別定義產出。
      最簡單的大小分,如果有 n 個參數,將會產出 2^n 個空間,定義起來就很累。
      
  • 模糊化類神經網路 … 略

結語

  • 運算方式,跟編程複雜度有關。
  • 函數式最好寫,但是彈性不高,產出結果通常有限(多樣性)。
  • 如果採用非連續性的就很痛苦,通常會使用離散化取數值分析,可用重心法。
  • 有重心法、肯定有眾數、中數法。
  • 一般來說函數式就夠用,世界萬物都是簡單構成複雜。
  • 可以利用收集資料,讓類神經網路產生演化結果 (稍後會提到),神經應該也是模糊的!
  • 收集到的資料正確性不知道有多高,根據簡單的投影法則,也可以變成模糊系統(初版)。

模擬退火

簡介

「模擬退火來自冶金學的專有名詞退火。退火是將材料加熱後再經特定速率冷卻,目的是增大晶粒的體積,並且減少晶格中的缺陷。」取自 wiki

簡單的說,膨脹去雜質,冷卻來精煉。冷卻得到區域最佳解,膨脹增加得到全局最佳解的機率。

操作

  • 以 f(x, y) = z 的函數,要找到全局最小值,圖形看起來就是 3D 模型。
    水往低處流,人往低處走
    
  • 當現在在 (x, y) 時,笨的方式就是往四處看看,看哪邊更小就往哪裡走出下一步。而高明的作法則是根據梯度(微分來了)低的地方走,您就講想您有一個重力感測器。
  • 步伐將會越來越小,這樣才能步步靠近區域最佳解。
  • 當相當靠近區域最佳解時,變小幅度(dx/dt)太小,那就跳到更遠的地方去吧,相當於容忍較差的環境。
  • 什麼時候容忍?可以根據某些指數函數結果跟隨機亂數比大小。

結語

  • 寫 ACM 題目時,通常會選擇隨機撒點,然後對於每一個點根據相同步伐走相同步數,逐一縮小步伐。因為跳出的容忍不好設計。
    foreach 隨機點
        for stepSize big to small
            for i = 0 to stepCount
                四處看看找更好的,Update 當前隨機點。
    
  • 簡單運用,找出多邊形費馬點、最小覆蓋圓 … 等。
  • 與隨機搜索差別在哪?隨機搜索相當於對每個子空間猜測,分布密度高才會準,空間越大,連區域最佳解都得不到。
  • 講到區域最佳解-看看咱們的政治人物,不外乎都是講那些事情,這樣就是區域最佳解。思維跳脫機率不夠高,看來是火不夠大。

基因算法

簡介

又稱 GA 算法,模擬生物遺傳的過程,根據「物競天擇,適者生存」的演化論,最後會得到最好的解答。而進行演化就是染色體的事情了,當一開始的多樣性夠,再搭配突變情況交織出來,那崇高的自然藝術便會出現。

看看人類,您覺得有適者生存嗎?那這樣會進化嗎?
有空去搜尋電影-《蠢蛋進化論》看看不願面對的真相?

操作

  • 將資料表示成基因片段,最簡單為二進編碼,當然也可以用實數。
    資料是什麼?函數的常數參數,來驅使我們的模型可以更接近收集出來的數據。
  • 第一步-初始化物種
    隨機產生基因片段,或者來個生物大滅絕保留可能好的再隨機生成。
  • 第二步-適應環境
    越接近收集出來的數據(差值總和越小),適應力越高。這就相當於成長階段。
  • 第三步-擇偶
    通常適應度高的會配在一起,就如人類有反例,這沒有絕對。
  • 第四步-交配
    交配方式如同染色體行減數分裂後的運作,將某幾段進行交換,而生物染色體只會切一刀然後配對,因為當初的雙股螺旋 … 各種原因,反正就是生物物質關係。如果是實數,則可以想像成會生成拉近關係或者是拉遠關係的結果。

    兩個好的物種交配,也不見得子代會好。

  • 第五步-突變
    個體突變,染色體的 01 互換機率,或者在實數方面特化或者是弱化(就是乘實數)。

設定集

  • 基因種類

    • 一般型基因原則
      DNA[i] 只會有 0 或 1
    • 實數型基因原則
      DNA[i] 可以是任意實數
    • 為什麼這麼分類?IEEE floating-point format 感覺不是好的方法?請自行思考,其中最大的原因是不應該侷限基因。
  • 一般型交配手法

    • 單點交配
      對兩段基因,隨機找索引 i,交換索引 i 之後的所有基因。
      i = rand_generate();
      for j = i to length
          swap(dna1[j], dna2[j])
      
    • 兩點交配
      與單點交配類似,不過是找一個區間 [l, r] 進行交換
      for i = l to r
          swap(dna1[j], dna2[j])
      
    • 字罩交配
      隨機挑數個隨機位置做交換。
    • 更多,您可以妄想。
  • 實數型交配手法

    DNA1[i]' = DNA1[i] + k * (DNA1[i] - DNA2[i])
    DNA2[i]' = DNA2[i] - k * (DNA1[i] - DNA2[i])
    k 取 [-1, 1] 的微量亂數。
    
  • 繁殖
    因為繁殖池大小有限,物種數量將會被約束。

    • 輪盤式選擇
      根據適應函數反應分布群族大小,四捨五入填滿整個繁殖池。
    • 競爭式選擇
      每次隨機挑選兩個,對於這兩個挑一個好的留下,直到繁殖池滿。
  • 更多設定

    • 基因長度:
      反應精準度、編碼方式。
    • 交配機率:
      機率高,容易產生混種!看看混血兒多聰明且吸引人,通常子代就不是如此。
    • 突變機率:
      機率太高反而是隨機搜索,調適好相當於爆炸式搜索。
    • 適應函數:
      如何反應好的物種?

結語

  • 應用-使用類神經網路的模型,利用基因算法找到最佳解。而每個神經元都有搭配的參數,就是把參數基因化,調用基因算法。
    幾句話說明類神經網路

    每個神經元根據所受到的刺激產出一個定值,而神經元也有階層關係,每一個階層間會互相刺激,最外層吸收外界資訊,慢慢細化傳入最後階段的神經元來反應。而 ‘刺激到產出’ 可以猜想為加權平均。

  • 實作後,這種算法必須應用在接近連續層面上會比較好,離散函數的問題效果不彰,也就是會有一些額外的判斷條件。
  • 擇偶相當困擾,通常根據隨機亂數,在排序後做選擇。
  • 交配相當刺激,同時也是最難抉擇的地方,個人造化。
  • 要不要適應繁殖?都行,適應好的物種就多複製幾個!// 看您要不要固定,不然數量會爆炸,或者加入篩選。
  • 大量繁殖大量突變,造就爆炸效應!(在鄰近空間進行爆炸找更好的地方)
  • 最後根本就是在玩突變,突變算法就此誕生!

螞蟻算法

簡介

螞蟻單一功能低,群體完成最佳化。螞蟻行動過程中會留下費洛蒙,隨著時間費洛蒙也會下降,在這反反覆覆的過程中,蟻群很有機會開創出全局最佳解。

螞蟻雖小,亦能驅象。

操作

  • 鮮少有人根據時間做迭代模擬的基底。
  • 由於模擬上相當困難,所以來點不科學的寫法,但仍要抓住費洛蒙的核心。
  • 第一版本-對於最短路徑搜索
    • 決定有多少隻螞蟻
    • 所有路徑上的費洛蒙初始為 0。
    • 決定要跑多少次迭代
    • 每次迭代,依序放出螞蟻,螞蟻會根據路徑上費洛蒙隨機走(也並不是越高越好),對於走比較好的路徑,將其走過路徑上的費洛蒙濃度增加。
    • 每次迭代,消散一點費洛蒙,來減少重複的錯誤區域解。
      這樣有什麼缺點?因為是依序放出螞蟻,所以相當不自然。
      再者每隻螞蟻還要有能力記錄走過的路徑。
      螞蟻的記憶能力有多高?
      
  • 虛擬碼

    Initialize
        Loop /* at this level each loop is called an iteration */
            Each ant is positioned on a starting node
            Loop /* at this level each loop is called a step */
                Each ant applies a state transition rule to     incrementally build a solution and a local pheromone     updating rule
            Until all ants have built a complete solution
            A global pheromone updating rule is applied
        Until End_condition
    
  • 第二版本-收集食物

    • 決定有多少隻螞蟻,並且隨機撒下。
    • 每隻螞蟻會搜索鄰近的食物
    • 根據概率撿起某個食物,朝向費洛蒙高的地方搬運。
    • 再根據概率將食物放下,放下時增加該地費洛蒙。

設定集

  • 費洛蒙的濃度消散函數
  • 螞蟻根據費洛蒙濃度的選擇函數
    • 不遵守?機率為何?
    • 遵守?又是根據什麼條件機率。

結語

  • 應用方面
    • 分群,把文章分類。
    • 搜索,各種 NPC 問題都可以拿來玩玩。
  • 小遊戲
    感覺攻城遊戲對於這方面相當有意思,不過此遊戲有炒地皮的設定,基礎建設越來越貴,各種不科學的情況,七八千分還算正常人吧,沒有搭載最佳化系統的素人。
  • 另外可見 DJWS的說明

粒子算法

簡介

英文名稱 Particle Swarm Optimization,粒子群聚演算法。看過鳥群群舞嗎?魚群穿梭嗎?

鳥群
圖片來源地址

在相互模仿效應中,牠們會向鄰近學習,部分保留、部分學習,這也是向其好的一面靠攏。

借由互相學習來調整群體面向,最後演化應該是會非常接近的群體。以人類來說,演化時間還不夠久 看起來個體智慧與能力的分歧度還相當大。根據演化結果,由於互動機率因歧異性而下降,導致演化不會趨近于一。

粒子演算法三項重點:評估,比較,模仿

  • 評估 - 目標函數值
  • 比較 - 根據評估結果比較,根據機率還是特定條件符合後
  • 模仿 - 將部分屬性(參數)模仿過來

操作

  • 一開始把族群撒在特定區域,並且賦予牠一個初速度。
  • 接著將會根據這個速度飛行。
  • 但是同時會根據鄰近或區域最佳進行模仿,速度矢量會有兩條(原本和模仿),兩個矢量根據參數調整後相加。
  • 慢慢地朝著某個方向飛行,帶頭的也會往其他的地方飛行。

結語

  • 單純模仿也行,只是要明白模仿對象是鄰居還是全局最佳。
  • 單純模仿的壞處在於搜索中的過程路徑會相當短,但是迭代次數應該會比較少次。
  • 如果是向鄰近模仿,可能是按照歐幾里德距離找最近幾個資料點。說不定會運用到 K-d Tree 這個資料結構。

反思題目

  1. (25%) 請說明模糊系統的構成要件為何 ? 其功能分別是 ? 如何建立模糊系統 ?
    其優缺點分別是 ?
    大體要件:模糊化機構、模糊推論引擎、模糊規則庫、去模糊化系統。

    模糊化機構:輸入有可信度問題,加以模糊。
    模糊推論引擎:將數個模糊規則合併篩選用途。
    模糊規則庫:每條規則將根據輸入產出相對應模糊輸出。
    去模糊化系統:將模糊產出的圖,進行調整最後以向量形式輸出。

    細節要件:模糊集合、模糊運算、模糊關係。

    模糊集合:用來表示一個函數對於某個條件的歸屬程度。
    模糊運算:表示每一個模糊集合之間的合成方法,用以做更複雜的組合。
    模糊規則:明確判斷條件 if else 轉換成模糊的判斷條件,即為模糊規則。
    模糊關係:在龐大的關係中,輔助綜合條件判斷的模型。

    建造模糊系統:通常由專家提供的語意規則建造,否則將會使用均勻切割的方式去建造模糊系統。
    優點:語意式的描述給予程式判斷上更大的彈性,不用撰寫非常明確的判斷條件於程式中,也能讓結果相當符合一般人的需求,而且後期可調整參數。
    缺點:可能沒有專家協助,模糊定義上很難得到好的結果。相較於明確判斷,去模糊化的過程速度會慢上許多,以及模糊運算上動用到的函數複雜度與所需時間成正比。

  2. (25%) 螞蟻是如何找到最短路徑 ? 請詳述 AS-TSP algorithm。
    就是那個每次回合,依序放出螞蟻,螞蟻根據費洛蒙走判斷條件走,最佳的走法將會在下一次運行時,路徑上的費洛蒙額外增加。

  3. (20%) 請詳述 RBF network 的架構為何 ? 如何訓練 RBF network ?
    全名:Radial basis function network
    架構有三層輸入層、隱藏層、輸出層。
    要素為非線性激活函數、向量形式的輸入輸出。
    在這門課中,採用基因算法來訓練它,根據與收集資料的誤差來當作適應程度,不斷地調整至好的參數。
    而在線性可分割的高維空間中,可以利用數學函數的運算再加上一個微量調整的偏量相乘,將整個函數慢慢導向至最好結果。(曾經所說的向量疊加,新的法向量 = 所在的法向量 + 微量 * 資料表誤差表示出來的向量。)

  4. (10%) 請說明有哪兩大類最佳化工具 ? 其優缺點分別為何 ?
    • 特定型最佳化法則
      快,一個問題一個算法。同一算法能解決的問題少,幾乎都要客製化。
    • 廣義型最佳化法則
      慢,無須根據問題調整算法。
  5. (20%) 請詳述 Genetic algorithm。其優缺點分別為何 ? 如何改進其缺點 ?
    優點

    1 与问题领域无关切快速随机的搜索能力。
    2 搜索从群体出发,具有潜在的并行性,可以进行多个个体的同时比较,robust。
    3 搜索使用评价函数启发,过程简单。
    4 使用概率机制进行迭代,具有随机性。
    5 具有可扩展性,容易与其他算法结合。

    缺點

    1 遗传算法的编程实现比较复杂,首先需要对问题进行编码,找到最优解之后还需要对问题进行解码。
    2 另外三个算子的实现也有许多参数,如交叉率和变异率,并且这些参数的选择严重影响解的品质,而目前这些参数的选择大部分是依靠经验。
    3 没有能够及时利用网络的反馈信息,故算法的搜索速度比较慢,要得要较精确的解需要较多的训练时间。
    4 算法对初始种群的选择有一定的依赖性,能够结合一些启发算法进行改进。
    5 算法的并行机制的潜在能力没有得到充分的利用,这也是当前遗传算法的一个研究热点方向。

    參考

  6. (20%) 請詳述 螞蟻算法。其優缺點分別為何 ? 如何改進其缺點 ?
    優點

    1 求解性能上,具有很强的鲁棒性(对基本蚁群算法模型稍加修改,便可以应用于其他问题)和搜索较好解的能力。
    2 蚁群算法是一种基于种群的进化算法,具有本质并行性,易于并行实现。
    3 蚁群算法很容易与多种启发式算法结合,以改善算法性能。

    缺點

    基本蚁群算法计算量大,求解所需时间较长。

    參考

  7. (20%) 請詳述 粒子算法。其優缺點分別為何 ? 如何改進其缺點 ?
    優點

    简单、易实现、计算量小和计算效率高

    缺點

    问题最主要的是它容易产生早熟收敛(尤其是在处理复杂的多峰搜索问题中)、局部寻优能力较差等。PSO 算法陷入局部最小,主要归咎于种群在搜索空间中多样性的丢失。

    改善

    (1)全局优化算法与局部优化算法混合
    (2)全局优化算法与全局优化算法混合。纵观各种与 PSO 算法相关的混合算法,大多数基本上采用一种策略对其改进,要么与其他算法,要么加入变异操作,同时采用两种策略的混合算法较少。

    參考


題外話

  • 關於單一感知機
    • 假設現在處於平面上,也就是說 f(xi, yi) = ci
      根據感知機會有三個變數,猶如 w[1] x + w[2] y + w[0]
      現在得到一堆 (xi, yi, ci) 是實際的情況,如何訓練感知機得到 w[] ?
      假設感知機會根據 (xi, yi) 產出 di
      根據調整參數 w’[i] = w[i] + wwww((yi - di))
      wwww 可以是任意函數,不過盡可能地介於 [0, 1]。
      會發現地,最後產出 di 會相當接近於 yi。
    • 當處於線性可分割,也就是可以一刀把兩個群族分開,那麼感知機是會收斂得到好的結果。
    • 也有另外一種方式,採用偏離向量的迭加,這個向量也會來自於產出的誤差效應。

Reference

  • NCU CSIE 計算型智慧課程
Read More +

敏捷方法 - 學習 (Agile Method)

敏捷開發

重點筆記

XP 極限開發

簡介

溝通為其特色,某方面來講有過於親密的傾向。
如果程序猿們按照 Pair Programming 的方式運行,被當成基佬們也不意外。

1. Fine scale feedback  細部回授
    * TestDrivenDevelopment via ProgrammerTests and CustomerTests (were UnitTests & AcceptanceTests) 
    * PlanningGame 
    * WholeTeam (was OnsiteCustomer) 
    * PairProgramming 
2. Continuous process rather than batch  非批次流程
    * ContinuousIntegration 
    * DesignImprovement (was RefactorMercilessly) 
    * SmallReleases 
3. Shared understanding  分享所知
    * SimpleDesign (DoSimpleThings, YouArentGonnaNeedIt, OnceAndOnlyOnce, SimplifyVigorously) 
    * SystemMetaphor 
    * CollectiveCodeOwnership 
    * CodingStandard or CodingConventions 
4. Programmer welfare  員工福祉
    * SustainablePace (original name: FortyHourWeek)
  • 強調團隊溝通,確保每一步都是正確且穩定。
  • 強調個人思考,藉由溝通引出每個人的思考。
  • 測試驅動開發,先有測試資料,才開始撰寫。

對於台灣人

  • 強烈抨擊文件不是首要任務,英文不好,還不如不要用英文撰寫。
  • 英文文件能提高溝通力?請自行反思。

回過頭來,看待敏捷

  • 文件越簡單越好,花在寫文件的時間可能太多。
  • 同一室工作,最多 10 人一室,以免過度干擾。
    • 溝通滲透-簡單說就是偷聽長知識。
    • 惡性溝通滲透-聽到沒有用的資訊。
  • 駐點客戶的存在
    • 與工程師溝通,確保需求符合,常駐程序猿們的公司,改完馬上可以詢問滿意。
    • 通常專案的費用,額外含駐點客戶員工的薪水。(畢竟不常在原公司)
  • 定期交貨,一分錢一分貨
    • 功能做到哪就給多少錢,風險分散。
    • 如果做失敗,可以即早治療。
  • 程序自動化測試
    • 採用連續整合 (可以去 CI 網站 看看)
    • 每天修改的程序,隔天起來就能查錯。

行動

  • 請參閱考古題條目,將會給你更多的執行項目。

做了一點小修改,馬上就能得到回饋,所以能敏捷。
敏捷不是快速,敏捷不是力量。雖然有點慢,但是穩定運作,避開不好的危機。
我們不是工廠!不是重複做相同的事情。

Lean Development 精實開發

1. Eliminate waste 根除浪費
2. Amplify learning 大量學習
3. Decide as late as possible 盡晚決定
4. Deliver as fast as possible 盡早交貨
5. Empower the team 授權團隊
6. Build integrity in 整合思維
7. See the whole 眼觀全局
  • 另一種軟體開發方式
  • 敏捷開發-共同向善,督促所有人進步。
  • 精實開發-剔除累贅,改善開發。

WHEN YOU ARE AGILE, YOU GET LEAN. 敏捷之後 自然瘦身

SCRUM

用以輔助 XP 極限開發的一種敏捷管理法

Role 主要角色

  • Product Owner
    • 產品負責人,負責在有限的時間和預算將產品做到最好。
    • 下面的人全照他的想法建造產品。
  • The Team
    • 團隊必須有產品製造過程中的技術。
    • 在每一個 Sprint 中,產出或增加軟體潛力。
      • The Team Resource
        開發前先餵點飼料,給予團隊之後會需要的資源。
      • Manual
        每一次 Sprint,制定軟體確切的模式(樣貌),這比寫文件更困難。
  • Scrum Master
    • 一個人管理和疏通所有程序猿、確認生存狀況以及環境障礙。
    • 程序猿通常有溝通上的障礙,需要有人引導。
    • 確認每一個人的進度,並且不會某些人有卡在相同問題(愚蠢狀況)。

Meeting 會議形式

  • Sprint Meeting
    • 產品負責人將會釋放出新的功能項目。
    • 團隊要根據技術去完成它們。
    • 在會議結束後,確定每個程序猿都知道如何去實作。
    • 會議兩周一次。
  • Sprint Demo
    • 開會期間,展示上次 Sprint 要求完成後的結果。
    • 同時檢查是否合乎預期,以及當初是為了造什麼來的。(工作不飽和,可能造出非物。)
  • Sprint Retrospective
    • 回顧和檢討,改善開發環境,可能是採用開發工具替換。
    • 或者是會議、討論形式的改善。
    • 最後同意並確定檢討後遵守的條目。
  • Daily SCRUM
    • 每個程序猿簡單報告這兩個星期做了什麼、中間遇到什麼問題、下次要完成什麼。
    • 如果遇到的問題可以自行解決,也可以協助或告知其他程序猿。
    • 這些技術或者是其他問題將要在 Daily SCRUM 後被解決。

Retrospective - 中文意思: 回顧
Sprint - 中文意思: 衝刺
Scrum - 中文意思: 爭球

Artifacts 神器

  • Increment 增量
    • 每次 Sprint,將軟體潛力增加,藉由當初定義 ‘完成(done)’ 為標竿。
    • 完成(down)
      每況愈下,完成的定義越來越嚴苛。最後如下定義:
      1.    All the PO’s defined acceptance tests run,
      2.    The system is fully integrated and running on the production servers,
      3.    All the manual pages are up to date,
      4.    The code is clean and well-factored,
      5.    All the programmer tests are running green.
      
    • 由於 ‘完成’ 定義嚴苛,即使有缺陷 (Bug),也能在短時間內修復。
    • 小檢查、小修復比起改造整個產品成本更低。
  • Product Backlog 產品待辦
    有序地完成需求項目,產品負責人和團隊要一致認可。
  • Sprint Backlog 衝刺待辦
    確認每一個 ‘done’ 的完成,看得到完成進度。

期中考古題

以下內容為本人網路搜索的轉換,如有錯誤請多多指教

  • 1 張氏軟體公司有張一張二張三張四等四位工程師及客戶公司派來的駐點使用專家王五, 另聘工讀生工一工二兩位。

    • 1.1 公司現場應如何佈置
      Answer. 
      1. 分 Common 及 Cave 兩區、和四周的 White Board(白版)
          **Common 區**: 兩人一組,在一台大尺寸螢幕前工作 (pair programming)                  各組可目視、交談、溝通
          **Cave 區**: 個人處理 e-mail,電話,閱讀資料等
          **White Board**: 供討論用
      2. 採用 Central Desk (相較於 U-pod) 配置,可以相互看到對方的工作區。
      3. 細節補充:
          1. 勿用需工人搬動的傢俱,用簡單桌子即可
          2. 電源線,網路線走底下或頭上,易接到桌子
          3. 椅子勿節省,有人因背痛要跪姿椅或升降桌
          4. 白板要很多,含輪子白板,相機白板,動態顯示板(連接投影機,如顯示 build 狀況)
          5. 見下圖 Central Desk 有 eye contact,U-Pod 則有 ear contact 且易看別組螢幕
      
    • 1.2 探索需求 誰做 何處做 產生何文件

      Answer. 客戶公司兩位資深人員做需求分析,在客戶公司做,產出功能清單及相關特性、限制、偏好。
          分析工作如下:
          1. 列出使用者名單
          2. 選取使用者樣本 
          3. 觀察、訪談(2),與之開會 
          4. 開會要充份討論 
          5. 會後得到功能清單,及相關特性、限制、偏好 
          6. 功能分次開發後,做喜好度調查
          最後派遣一位當作駐點客戶給開發團隊即可。
      
          對於顧客
          * 顧客不明白他自己需要什麼
          * 顧客不願將他們的需要固定在一系列寫在紙上的條例中
          * 在價格和時間確定後,顧客堅持要求新的需要
          * 分析者與顧客的通訊太緩慢
          * 顧客不參加回顧或無法參加回顧
          * 顧客缺乏技術上的知識
          * 顧客缺乏對軟體開發的知識
          ----
          對於分析師
          * 是否可行
          * 是否在規定的時間裡可以完成
          * 價格上是否負擔得起
          * 是否合法
          * 是否符合道德
      
    • 1.3 Scenario 誰做 文件為何
      Answer. 駐點客戶說明,並寫出 Scenario 和 User Story 文件。
          * 寫使用情節 (Scenarios) 並與開發者確認使用畫面,
          * 撰寫方式:由簡而繁、由正常到異常
      
    • 1.4 Acceptance Test Case 誰做 文件為何
      Answer. 駐點客戶寫,並且產出 驗收案例文件。
          * 由使用情節寫驗收測試(需準備大量 data )
          * 驗收測試應在程序員寫代碼之前就寫好。
          * 根據使用使用操作,會產生何種操種介面或者是輸出。
      
    • 1.5 CRC session 誰做 文件為何

      Answer. 工程師五人以內圍坐,產出 Class Diagram, Sequence Diagram 等設計圖文件
          * 群體智慧,設計出好的程式架構
          * 切割類別(C)、每個類別自己要做什麼(R)以及類別的合作類別(C)
      
          架構設計會議,準備 CRC Card (Class-Responsibility-Collaborator cards) 
          以下為 CRC Card 的欄位項目 (相當於 O-O 架構的設計)
          * 資訊保持者(information holder) ─ 知道或提供資訊,也就是說保持事實,例如郵件地址,帳號,交易記錄等;
          * 結構者(structurer) ─ 保養物件間的關聯以及與這些關聯相關的資訊,例如檔案系統的folder;
          * 服務提供者(service provider) ─ 執行工作,一般來說提供運算服務,例如信用授權;
          * 協調者(coordinator) ─ 委託工作,例如交通號誌燈,文字處理器的字體管理;
          * 管制者(controller) ─ 決定並指揮它物的行動,例如交通指揮員;
          * 介面者(interfacer) ─ 支持系統內外各部門的間通訊,例如ATM的金錢出口。
      
          決定以上內容後
          * 可以撰寫 Class header 和 Method header 的簡單說明。
          * Class header 由其下 Method header 匯集篩選而成。
      
    • 1.6 Dispatching and Scheduling 誰做 文件為何
      開發條目
      Answer. 工程師們根據自己的狀況,將認領的類別 Class 估算工作天數。產出每個人要在這段期間內完成那些功能項目的文件。
          Dispatching - 派工 (有人可能完成不了某些項目,著手工作分配)
          Scheduling - 時程 (功能所需完成時間進行分配)
          * 每一回合 - 平均三周,做一次派工和時程規劃 (工作分配,時間分配)
          * 每三回合 - 平均兩個月,交貨給客戶
      
    • 1.7 Unit test planning 誰做 文件為何
      Answer. 由工程師撰寫對於每個類別 Class method 的測試代碼 (根據之前 CRC 的討論),產出 Unit test code
          * 這玩意必須在程式撰寫前開始,而且通常比源代碼還長。
          * Test code 又稱 Test-First Development。
          * 不知道算不算 **測試驅動開發** 前置作業
          * 每一個 method 根據參數、環境做預期結果的測試。
      
    • 1.8 Data structure design 誰做 文件為何
      Answer. 工程師,產生數據結構的 Class。
          * 除了工程師外,沒人辦得到。
          * 高級數據結構比一般數據結構好用,而且擴充性和彈性較強。
          * 通常內建標準函數庫就很好用
          * C++: #include <stack>, #include <queue>, ...
          * Java Collections Framework: ArrayList, Vector, Stack ...
      
    • 1.9 Algorithm design 誰做 文件為何
      Answer. 工程師,產出虛擬碼 pseudo code、設計草圖 design sketch
          * 虛擬碼不說自明,設計草圖就是圖形化的想法來源
          * 根據數據結構也有所不同。
          * 演算法也是有抽象層次 Abstraction levels,相互調用什麼的。
          * 要做 Trace test code 來 Debug。
          * 要做時間複雜度分析。
          * 同時簡化到可以在白板上,讓團隊審查 Group review。
      
    • 1.10 Coding 誰做 文件為何
      Answer. 工程師,產出源代碼 source code
          * 終於開始工作,還會一直被 Unit test code 
          * 程式易於閱讀、了解、維修,才是 **活著**
          * 強調重複利用別人代碼 (因為通常已經通過測試,不用 Debug)
      
    • 1.11 Unit testing 誰做 使用何文件
      Answer. 工程師使用測試軟件運行 Unit test code,產出測試結果。
          * 如 Java unit test,產出測試記錄檔,表示哪些 method test case 通過。
      
    • 1.12 Acceptance testing 誰做 使用何文件
      Answer. 駐點客戶手動測試,使用驗收案例文件,產出測試結果。
          * 手動操作所有驗收案例
          * 如果驗收案例太多,那也是駐點客戶疲累的地方。
          * 測試文檔,不外乎就是哪些連續動作 (Action) 通過或者是不通過
      
    • 1.13 Reverse Engineering Tool 何工序後可使用
      Answer. 在架構設計 (CRC) 後,便啟動這類型逆向工具。
          * 利用逆向工程工具 如 eUML2、AgileJ。
          * 工具將動態產生 Class diagram, Sequence diagram ... 等。
          * 協助設計草圖不偏離,同時能了解設計樣貌,幫助維護和修改。
      
    • 1.14 此軟體的需求有七個功能( user story ) 駐點使用專家規劃為三次交貨( release )工程師們規劃用兩個回合( iteration )完成第一次交貨的功能
      • 1.14.1 派工 (dispatching) 如何做
        Answer. 在 CRC 工作結束後,每個成員認領一項類別 Class 進行開發。而在每回合微調工作分配。
        
      • 1.14.2 時程 (scheduling) 的時間單位為何
        Answer. 平均 2-3 週
        
      • 1.14.3 工作中客戶公司會不會來催進度為什麼
        Answer. 定期交貨,以執行力達成承諾取信客戶,客戶只需固定時程檢驗進度。
        
  1. 因有 Continuous Integration(CI) 使 Agile method 不須 integration testing. Explain it.
    Answer. 連續整合採用自動化的方式進行,每一天或者是固定時間,便會將團隊開發、撰寫立刻回饋分析結果,如此一來不用人工繁瑣的整合測試程序。
        * 這問題相當奇怪,因為連續整合也算是整合測試 ?
        * 連續整合不用人工測試,可以降低風險。
        * 連續整合隨時都有可以發布的版本。
        * 增加系統透明度。也就是說可以追蹤或者是預測發展趨勢。
    
  2. Test-driven development 的 development, test 及 drive分別是什麼
    Answer. 因為在源代碼 source code 撰寫開始前,必須先把所有測試項目撰寫成 test code 或者是人工驗收的案例,
    * development 開發方式,做事的風格
    * test 測試,經由 test code, case, tool 產生預期結果和實際形況的差異分析。
    * drive 驅動則是根據測試結果驅使源代碼的修正。
    
  3. 維修軟體時,應閱讀 sourse code 或 pseudo code? Why?
    Answer. Pseudo code,方便理解與快速找到要維修的地方。
        * 題目應為先讀哪一項,照理來講要先讀 pseudo code 再讀 source code。
    
  4. Pair programming 何以能提高軟體品質?
    Answer. 一人撰寫一人修正,分散思考壓力,同時可以激發出創意,可以降低錯誤率、提升除錯效率。
        * 主要是分散思考壓力、增加思考廣度。
        * 缺點是開發時間會稍慢,但是品質不錯。
        * 編程能力水準相當才能相互激發,否則是純教導或者是管理功用。
        * [搞笑影片](https://www.youtube.com/watch?v=dYBjVTMUQY0)
    
  5. Method interface 與 method header 有何相關舉例說明之。
    Answer. 
    1. method interface 指的是關於這個 method 參數型態和意義、以及額外調用的 method 說明。
    2. method header 指的是在 method 前面的說明,通常具有這個 method 如何快速簡易使用的說明。
            * 通常 method header 算是 method interface 的摘要,或者是組合使用的說明。
            * 因此 method interface 完成後,才會有完整的 method header。
            * method interface 指的並不是 java 的某種 interface 類別,而是類似 UML 有哪些 method 和 attribute,能提供做出什麼事情。
            * 別跟 class header 搞在一起,請弄清楚。
    
  6. Data structure design 與 Algorithm design 有何關係
    Answer. 演算法中會調用到資料結構,根據搭配的資料結構才能估算時間複雜度,以及支持效果。同時,演算法也能針對搭配資料結構做最佳化。
        * 面相來說,Data structure 是工具 Tool。
        * 怎麼最佳化使用工具就是演算法的事情。
        * 例如: 資料結構的幾種操作的複雜度不同,調用操作的比率將會是演算法的重點。
    

Reference

Websites

  1. 台灣敏捷苗圃
  2. BLOG - 輕鬆談軟工
  3. Wiki

Friends

  • Iris
  • 等待更多網友
Read More +

解決 Hexo Comment !

評論 Widget 設定

為什麼會有這篇文章

  • 你的主題可能沒有 recent_comment.ejs
  • Comment 可能是 多說Duoshuo 而你不喜歡

開始正文

使用 Disqus

  • 請到 Disqus 申請帳號,並且記住你的 shortname

    • 到本機下,修改本機目錄下的 _confid.yml 在 disqus_shortname 貼上自己的 shortname
    • 接著,就是確認運行成功。
      1
      2
      # Disqus
      disqus_shortname: morris1028
  • Widget 側欄的近期評論,當然還有熱門、聚合 … 等。請參考 這裡

    themes/xxxx/layout/_widget/recent_comment.ejs
    1
    2
    3
    4
    <div id="recentcomments" class="dsq-widget">
    <p class="asidetitle">Recent Comments</p>
    <script type="text/javascript" src="http://morris1028.disqus.com/recent_comments_widget.js?num_items=10&hide_avatars=1&avatar_size=32&excerpt_length=100&hide_mods=0"></script>
    </div>
  • 關於主題可能沒有 comment.ejs,請在目錄下增加代碼
    themes/xxxx/layout/_partial/comment.ejs
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <% if (page.comments){ %>
    <section id="comment">
    <h1 class="title"><%= __('comment') %></h1>
    <% if (theme.comment_provider == "facebook") {
    if (theme.facebook) { %>
    <%- partial('_partial/facebook_comment', {fbConfig: theme.facebook}) %>
    <% } %>
    <% } else if(config.disqus_shortname) { %>
    <div id="disqus_thread">
    <noscript>Please enable JavaScript to view the <a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
    </div>
    <% } %>
    </section>
    <% } %>
  • 萬一還是啟動不成功,請查閱 after_footer.ejs 是否具有以下代碼
    themes/xxxx/layout/_partial/after_footer.ejs
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <% if (config.disqus_shortname){ %>
    <script type="text/javascript">
    var disqus_shortname = '<%= config.disqus_shortname %>';
    (function(){
    var dsq = document.createElement('script');
    dsq.type = 'text/javascript';
    dsq.async = true;
    dsq.src = '//' + disqus_shortname + '.disqus.com/<% if (page.comments){ %>embed.js<% } else { %>count.js<% } %>';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    }());
    </script>
    <% } %>
  • 評論 CSS 設置,請到 comment.styl 查閱
    themes/xxxx/source/css/_partial/comment.styl
    1
    2
    3
    4
    5
    6
    7
    8
    #comment
    padding 20px
    background #272822
    box-shadow 1px 2px 3px #ddd
    margin-bottom 50px
    .title
    font-weight normal
    margin-bottom 15px
    • 最後再確認一下,有載入 comment 的 CSS
      theme/xxxx/source/_partial/css/style.styl
      1
      @import '_partial/comment'

更多

  • 其實差不多了,想必也能配置成功。
  • 關於近期文章 widget
    themes/xxxx/layout/_widget/recent_comment.ejs
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <% if (site.posts.length){ %>
    <div class="categorieslist">
    <p class="asidetitle">Recents</p>
    <ul>
    <% site.posts.sort('date', -1).limit(5).each(function(post){ %>
    <li>
    <a href="<%- config.root %><%- post.path %>"><%= post.title || '(no title)' %></a>
    </li>
    <% }) %>
    </ul>
    </div>
    <% } %>
  • 最後在 themes/xxxx/_config.yml 加入您的 widget
    themes/xxxx/_config.yml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #### Widgets
    widgets:
    - recent_posts
    - category
    - archive
    - tagcloud
    - recent_comment
    - links
    - rss

最後

非常感謝您的閱讀

Read More +

第一次來到 Hexo !

加油

失敗就是失敗

看著右上方的清單,還真有 wiki 的感覺,對於長篇大論是挺有用的,現在應該說是裝飾,接下來要描述失敗的開始。

這是一個搬運的過程,但是宣告失敗

初章

為了轉移過來,將 Morris’ blog(PChome) 文章倚靠爬蟲方式轉移過來,但是沒想到這裏要的是 markdown 檔案格式,用 Nodejs 寫了巨噁無比的代碼來專屬爬 PChome 新聞台,並且使用套件將其轉換成 markdown。

最後宣告失敗。

用了不少可以將 html to markdown 的工具,或者只是單純要 html to text,但是不管哪個產出的格式都不好,心灰意冷的情況下,開始動工修改 node_modules 資料夾下的插件代碼,track 相異插件各種作噁,最後還是沒成功。

次章

目前以玩玩的心態架設這個靜態頁面。

附上 20140411 BACKUP Morris’ blog(PChome) backup

nodejslink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
var http = require('http'),
fs = require('fs');
var toMarkdown = require('to-markdown').toMarkdown;
var htmlToText = require('html-to-text');
/*
var text = htmlToText.fromString('<h1>Hello World</h1>', {
wordwrap: 130
});*/
// console.log(toMarkdown('<b>Hello world</b>'));
var websiteName = "zerojudge";
var websitePage = 141;
var websiteDomain = 'http://mypaper.pchome.com.tw/';
var url = websiteDomain + websiteName;
var loadprocess = 0;
clawingWebSite(url, websitePage);
function clawingWebSite(url, websitePage) {
for(var i = 0; i <= websitePage; i++) {
if(i == 0)
clawingWebPage(url);
else
clawingWebPage(url + "/P" + i);
}
}
function clawingWebPage(url) {
readWebPage(url);
}
function branchWebPage(source) {
var sourceIndex = source.indexOf('class="blog"');
while(sourceIndex >= 0) {
var pageLink = source.indexOf(websiteName + '/post', sourceIndex);
if(pageLink > 0) {
var endLink = source.indexOf('"', pageLink);
var articleLink = source.substr(pageLink, endLink - pageLink);
readWebArticleLink(websiteDomain + articleLink, articleLink);
sourceIndex = pageLink + 1;
sourceIndex = source.indexOf('title brk_h', sourceIndex);
} else {
break;
}
}
}
function parsingArticlePage(source, fileName) {
var contentBody = "";
var articleTitle = "";
var mdFormat = "";
var sourceIndex = source.indexOf('name="keywords"');
sourceIndex = source.indexOf('content="', sourceIndex);
var nextIndex = source.indexOf('"', sourceIndex + 10);
articleTitle = source.substr(sourceIndex + 9, nextIndex - (sourceIndex + 9));
sourceIndex = nextIndex;
console.log('Title = ' + articleTitle);
sourceIndex = source.indexOf('<div class="innertext brk_h"');
var endIndex = source.indexOf('<div id="ArticleMapTitle"');
contentBody = source.substr(sourceIndex, endIndex - sourceIndex - 1);
contentBody += "</div>";
var sourceBody = contentBody;
if(endIndex - sourceIndex - 1 <= 0)
return;
articleTitle = articleTitle.replace(/\[/g, "【");
articleTitle = articleTitle.replace(/\]/g, "】");
var text = htmlToText.fromString(sourceBody, {
wordwrap: 130
});
contentBody = toMarkdown(contentBody);
mdFormat += "title: " + articleTitle + "\n";
mdFormat += "date: 2014-04-10 20:10:28" + "\n";
mdFormat += "tags: " + "\n";
var tagIndex = source.indexOf('<div id="article_tag">');
if(tagIndex > 0) {
tagIndex += '<div id="article_tag">'.length + 1;
var tagTail = source.indexOf('<div id="article_author" align="right">');
var tagEndIndex;
while(true) {
var tagStartIndex = source.indexOf('search_fields=tag">', tagIndex);
tagStartIndex += 'search_fields=tag">'.length;
if(tagStartIndex < 0 || tagStartIndex > tagTail)
break;
tagEndIndex = source.indexOf('</a>', tagStartIndex);
var articleTag = source.substr(tagStartIndex, tagEndIndex - tagStartIndex);
console.log(articleTag);
mdFormat += "- " + articleTag + "\n";
tagIndex = tagEndIndex;
}
}
mdFormat += "---" + "\n\n";
text = " " + text;
text = text.replace(/\n/g, "\n ");
mdFormat += text;
loadprocess++;
fs.open('sourcePage' + loadprocess + '.html', 'w', 0666, function(e, fd) {
if(e) {
console.log('错误信息:' + e);
} else {
fs.write(fd, source, 0, 'utf8', function(e) {
if(e) {
console.log('出错信息:' + e);
} else {
fs.closeSync(fd);
}
});
}
});
fs.open('textPC' + loadprocess + '.md', 'w', 0666, function(e, fd) {
if(e) {
console.log('错误信息:' + e);
} else {
fs.write(fd, mdFormat, 0, 'utf8', function(e) {
if(e) {
console.log('出错信息:' + e);
} else {
fs.closeSync(fd);
}
});
}
});
fs.open('oldPC' + loadprocess + '.md', 'w', 0666, function(e, fd) {
if(e) {
console.log('错误信息:' + e);
} else {
fs.write(fd, contentBody, 0, 'utf8', function(e) {
if(e) {
console.log('出错信息:' + e);
} else {
fs.closeSync(fd);
}
});
}
});
}
function readWebArticleLink(url) {
http.get(url, function(res) {
var source = "";
//通过 get 请求获取网页代码 source
res.on('data', function(data) {
source += data;
});
//获取到数据 source,我们可以对数据进行操作了!
res.on('end', function() {
parsingArticlePage(source);
});
}).on('error', function() {
console.log("获取数据出现错误");
});
}
function readWebPage(url) {
http.get(url, function(res) {
var source = "";
//通过 get 请求获取网页代码 source
res.on('data', function(data) {
source += data;
});
//获取到数据 source,我们可以对数据进行操作了!
res.on('end', function() {
branchWebPage(source);
/*fs.open('hello.txt', 'w', 0666, function(e, fd) {
if(e) {
console.log('错误信息:' + e);
} else {
fs.write(fd, source, 0, 'utf8', function(e) {
if(e) {
console.log('出错信息:' + e);
} else {
fs.closeSync(fd);
}
});
}
});*/
});
}).on('error', function() {
console.log("获取数据出现错误");
});
}
Read More +

從現在開始開始 Hexo !

用了 GitHub, 學到 Nodejs, 路過 Hexo, 到了這裡

安裝各種有趣 ?

Hexo 第一步

  • 請先把 Nodejs 和 npm 架設好
  1. 下載 Hexo
    1
    $ npm install hexo -g
  2. 安裝到你的目標目錄下
    1
    $ hexo init blog && cd blog
  3. 以下操作會將文章從 markdown 檔案產生關聯
    1
    $ hexo generate
  4. 開啟 Server, 使用於本地調效, 之後可連到 http://localhost:4000/ 查看
    1
    $ hexo server

Hexo 日常問題

  • 撰寫文章

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ hexo new [layout]
    $ hexo new "New Post"
    # => The file will be created at source/_posts/new-post.md
    $ hexo new page "New Page"
    # => The file will be created at source/new-page/index.html
    $ hexo new draft "New Draft"
    # => The file will be created at source/_drafts/new-draft.md
  • 文章標籤使用

    1
    2
    3
    4
    title: Start Hexo !
    date: 2014-04-10 19:40:22
    tags: [hexo, image]
    categories: About This Blog
  • 文章代碼高亮

    1
    2
    3
    {\% codeblock \%}
    your code here. 自行去掉反斜線
    {\% endcodeblock \%}

Hexo 個人化問題

  • 修改主題, 修改完畢後, 請進行以下操作來對 deploy 運行, style.css 才會正確, 本地查閱不影響

    1
    2
    3
    $ hexo clean
    $ hexo generate
    $ hexo deploy
  • 與 github page 連接做靜態操作

    blog_folder/_config.yml
    1
    2
    3
    4
    5
    6
    # Deployment
    ## Docs: http://zespia.tw/hexo/docs/deployment.html
    deploy:
    type: github
    repository: https://github.com/morris821028/morris821028.github.io.git
    branch: master
  • RSS 設定

    blog_folder/_config.yml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # Plugins
    plugins:
    - hexo-generator-feed
    - hexo-generator-sitemap
    # RSS hexo-generator-feed
    feed:
    type: atom
    path: atom.xml
    limit: 20
  • BLOG 主題 pacman 配置 - 增加文章列表圖片 (詳見 http://yangjian.me/pacman/hello/introducing-pacman-theme/)

    blog_folder/theme/pacman/layout/_partial/post/article.ejs
    1
    2
    3
    <@ if(item.content.indexOf('<img src="') >= 0) { @>
    <p itemprop="description"><img style='float:left;margin:5px;height:80px;' src="<@- item.content.substring(item.content.indexOf('src="', item.content.indexOf('<img src="')) + 5, item.content.indexOf('"', item.content.indexOf('<img src="') + 11)) @>">
    <@= strip_html(item.content).replace(/^\s*/, '').replace(/\s*$/, '').substring(0, 140) @></p>
  • BLOG 主題 pacman 配置 - 色彩配置

    blog_folder/theme/pacman/css/_base/variable.styl
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    color-background = #1f1f1f
    color-font = #ffffff
    color-white = #ffffff
    color-blue = #2ca6cb
    color-theme = #1f1f1f
    color-font-nav =#E9CD4C
    color-section = #272822
    color-footer = #1f1f1f
    color-gray = #CCC
    color-heading = #333333
    color-code = #eee
    color-twitter = #00aced
    color-facebook = #3b5998
    color-weibo = #eb182c
    color-google = #dd4b39
    color-qrcode= #49ae0f
    color-top = #762c54
Read More +