2020/12/16

利用 GitHub Actions 發布 React app 到 GitHub Pages

最近有佛心同事開了 React 教學工作坊
赫然發現自己已經好久沒有寫 UI 相關的程式了
果然是用進廢退
不過上了幾次課之後
一些相關的感覺又慢慢找回一點點

上完課後自己又重新作了一次工作坊上的 lab
忽然想到
若是要給別人看看自己寫的 React app
能否用 GitHub Pages 當作一個 demo site
又想到可以用 GitHub Actions 來佈署 GitHub Pages
基於上述的想法
蒐集了一些資料來玩玩看

首先是將 React app 放到 GitHub Pages 上
主要是參考西打藍 Siddharam 這篇文章 - 將create-react-app佈署到GitHub Pages
不過裡面是在 local 利用 gh-pages 這個套件
作出發布用的資料夾後
把東西推到自己 repository 的 gh-pages branch 內


設定 dev 相依套件 gh-pages 以及 homepage 屬性


接著要利用 GitHub Actions 作到自動佈署 GitHub Pages
參考找到的 Christoph Michel 這篇 - How to deploy a create-react-app with github-actions
裡面提到要讓 GitHub Actions 能夠作 git push
必須設定一個 deployment key
文章內有說明步驟
或是參考 GitHub 官方文件也可以很輕鬆完成


設定 deploy keys 跟 repository secrets


不過 Christoph Michel 那篇介紹的是
當每次 git push 到 master branch 時
會自動觸發 GitHub Actions 來發布
但我想要一種情境是
我可以手動選擇要發布的 branch
例如我可能作了兩個版本
個別放在 branch A 與 branch B
我想要隨時可以手動發布 branch A 或是 branch B 到 GitHub Pages
參考 Adam McArthur 這篇 - How to Manually Trigger a GitHub Actions Workflow
學到了一個手動觸發的 event - workflow_dispatch


手動觸發事件 - workflow_dispatch

最後放上這個 repository 給有興趣的人參考
https://github.com/LaurenceCheng/react-workshop-2020-winter

參考資料:

1. create-react-app docs
2. 將create-react-app佈署到GitHub Pages - 西打藍 Siddharam
3. How to deploy a create-react-app with github-actions - Christoph Michel
4. How to Manually Trigger a GitHub Actions Workflow - Adam McArthur
5. Working with GitHub Pages - GitHub Docs
6. Managing deploy keys - GitHub Docs
7. Manual events - Events that trigger workflows - GitHub Docs

2020/11/24

在 Windows 上用 PyCharm 開發, 在遠端 Linux 上執行

情境是這樣的

我想在 Windows 上使用 JetBrains 的 IDE - PyCharm 作開發
但是在遠端的 Linux 上執行開發好的 Python 作測試

基本上 JetBrains 的文件算是寫得蠻清楚的

首先先看一下 Linux 上的環境大概是怎樣
我以一台 AWS EC2 的機器當作遠端的 Linux
怎麼開 AWS EC2 跟怎麼連上開好的 EC2 我就不說明了
可以去看 AWS 的文件 [Launch your instance][Connect using WSL]
還有一個等等會用到的 [Connect using PuTTY]
裡面有教怎麼用 PuTTYgen 把 private key 從 .pem 轉出 .ppk 檔
後面 PyCharm 連線時會需要 .ppk 檔

首先,在遠端的 Linux 上安裝好 Python 3.7.9 以及作好 venv 的設定
我們放了一個測試的 mytest.py 在 /home/ec2-user/ec2_python3_workdir 中
當作遠端的環境


遠端的 Linux


接著啟動 PyCharm 開啟本機的對應的資料夾
我的情境是本機與遠端的資料夾
是同一個 repository 的 working copy
(不過後來發現其實遠端不必是 git 的 working copy)


啟動 PyCharm 選擇開啟本機資料夾


進入後可以發現有 Python interpreter 設定的警告訊息
接著進入 File 選單開啟設定


選擇 File -> Settings


進入設定之後,點選 Python Interpreter 項目
在右邊的區塊可以看到 Python Interpreter 的下拉選單顯示 "<No Interpreter>"
所以我們點擊選單右邊的齒輪按紐
準備新增一個 Python Interpreter


新增 Python Interpreter


新增的時候選擇 SSH Interpreter
在介面上點擊 Existing server configuration 右邊的 "..." 按鈕
建立新的 SSH configuration


建立 SSH configuration


進入到 SSH Configurations dialog 後
點擊左上角的 "+" 可以新增 SSH configuration
在右邊的連線資訊中輸入 EC2 的 FQDN 與 User name
Authentication type 選 Key pair 後
在 Private key file 中填入一開始我們轉換好的 .ppk 檔


填入遠端 Linux 連線資訊


按下 Test Connection 按鈕
確認填入的資訊是可以成功連上遠端 Linux 機器的
接著按下 OK 直到回到 SSH Interpreter 那個 dialog 後按 Next


測試連線成功


下一步是設定遠端 Linux Python 的路徑
我們因為有用 venv 的關係
所以路徑設定為 /home/ec2-user/ec2_python3_workdir/.venv/bin/python3
這裡可以直接瀏覽遠端 Linux 上的檔案系統
選好後按下 OK


選擇遠端 Linux 要使用的 Python interpreter 路徑


再來設定本機與遠端同步的資料夾
就設定到 /home/ec2-user/ec2_python3_workdir
這個設定是讓之後在本機上的修改
都會上傳到遠端 Linux 的這個路徑中
設定好後就一路 OK 到底
然後回到原本 Project 的介面


設定同步資料夾


這時候可以打開 Remote Host 的視窗
展開到我們設定同步的資料夾時
可以看到綠色的 highlight
每次修改本機檔案後儲存
可在右下角 File Transfer 視窗看到 PyCharm 在幫我們上傳


本機編輯後可自動上傳至遠端 Linux


最後就是按下執行
在左下角的 Run 視窗能看到執行結果
也可以透過右邊 Remote Host 視窗開啟遠端的檔案來看
到這一步算是完成了本機開發遠端執行的目的
後續要接著執行 unit test 並在 PyCharm 的介面上看到各項測試綠燈也是可以的


遠端執行修改後的結果

2020/03/02

在 Windows 上用 Visual Studio 2019 開發 Linux C++ 程式

情境是這樣的

我已經存在一個 repository 寫好了 Makefile
可以在 Linux 上透過 make 編譯出執行檔
想用 Visual Studio 開發並 debug 這樣一個程式

手上有的環境跟 GitHub repository

其實 Microsoft 官方文件介紹得非常清楚
跟著文件做就可以很簡單的建立一套開發環境

首先在 Visual Studio 上必須先安裝 Linux development with C++ 的 workload

安裝 Linux development with C++ in vs2019

接著在你的 Linux 系統上確認有安裝需要的套件
g++, gdb, rsync, zip, make, openssh-server 等

然後啟動 Visual Studio 後進入 Tools > Options 選單
在 Cross Platform > Connection Manager 頁面按下 Add 按鈕
並輸入連線的資訊
當然可以使用 SSH Private Key 的方式做認證

設定與 Linux 的連線

輸入與 Linux 連線的資訊

接著就可以建立新的專案
選擇 Makefile Project (for Linux) template
路徑設定在我們已經有的 repository 資料夾內
因為後續路徑關係
我們把 .sln 跟 .vcxproj 兩個檔案放到跟 Makefile 同一層

建立 Makefile Project

選擇在原本 Linux 程式的 repository 資料夾下建立

把 .sln 與 .vcxproj 移動到 Makefile 同目錄

再來把所有相關的 sources 跟 Makefile 都加入專案內
接著進入 Project > Properties 選單
在 Remote Build 頁面的 Build Command Line 設定填入 make all
最後按下 Build Solution (Ctrl + Shift + B)

加入已存在的檔案

設定 Remote Build

可以看到執行建置時, 複製到遠端 Linux 並執行 make all

這時候可以在 Linux 裡面發現被複製過去的檔案
default 會在使用者的 home 路徑下的 projects 資料夾
這個路徑也能在 Project Properties 裡修改

設定複製到遠端 Linux 的路徑

檔案被複製到 Linux 上的樣子

最後設定 debugging 的資訊
跟以往在 Windows 上的設定類似
不過路徑改為遠端 Linux 上的
執行沒問題後就可以加上一些 breakpoints 來試試看吧

設定 debugging 啟動資訊

用 Visual Studio 2019 debug Linux C++ 程式的過程

我沒有使用更多深入的功能
但就目前有接觸到的基本功能來說
體驗算是與原本開發 Windows C++ 程式非常一致
很快就可以上手

2020/02/17

[自己的 Hackathon] L10 盃黑客松之即時開票系統 - 回顧

簡單回顧一下這次自己的黑客松

Azure Cost

Google API Dashboard
最後因為 Azure Functions 沒有真的跑在雲端上
所以只有 Storage 被收了點錢
Google Sheets API 打了四千多次

What went well?


能快速從文件
以及可搜尋到的教學材料中學習
只有在最後上了雲端後
不知道為什麼 Azure Functions 會一直取得同樣的值
但運氣很好的有發現可以用本機執行替代

再者是有先簡單規劃要完成的小項目
這樣可以在短時間內聚焦目標
做比較快的衝刺

What needs improvement?


這次我建立一個 HTTP 觸發的 Azure Functions 當作測試使用
但是如果使用單元測試
我相信在開發核心邏輯上應該可以做得更快
畢竟每次測試都必須在本機啟動 Azure Functions
雖然沒有特別慢
但我假設單元測試應該可以執行得更快
對於除錯或是快速迭代很有幫助
運氣不錯這次重構並沒有改出問題
(是的, 我有花時間重構)

用 Visual Studio Code 寫 python
不能說非常好用
只有一些很基本的重構功能
我還遇到 extract method 把 code 搞亂的情形
也許下次寫的時候可以改用 PyCharm 試試看

非常不熟系上線到雲端後的各種觀測系統
下次也許要多花點時間理解怎麼使用那些工具

Something learn


  • 學會怎麼用 pandas 取得網頁的資料
  • 學會用 python 呼叫 Google Sheet API
  • 學了幾個 Google Sheet functions
  • 學會怎麼開發/測試/佈署 Azure Functions

Future works


這次的系統就是給朋友們自己使用
大約十人左右的流量
而且是利用 Google Spreadsheet 來做 renderer
蒐集了大家使用上的意見
也許下一次大選的時候可以考慮用更有趣的前端來作呈現
這次天下雜誌有做了一個很不錯的系統
希望下次自己可以玩出一些有趣的東西

最後附上這次 hackathon 的 github repo - https://github.com/LaurenceCheng/2020Election

2020/02/14

等寬字型比一比 - JetBrains Mono、Fira Code、Cascadia Code、Consolas 在 Visual Studio Code 的樣貌


上個月在 facebook 上分享了 JetBrains 出了一款等寬字型叫 JetBrains Mono
昨天免費資源網路社群剛好也寫了一篇
"JetBrains Mono 更適合閱讀程式碼的等寬字型,內建四種字重斜體可商用"
在介紹這個字型

之前也有看過 Fira Code 以及微軟出的 Cascadia Code
趁這機會測試比較一下這幾種等寬字型
我是使用 Visual Studio Code 當作測試用的 IDE
以下是各種字型的截圖

Consolas

Cascadia Mono PL

Cascadia Code PL

Fira Code

JetBrains Mono
我原本都是使用 Consolas
未來會試著改用 Fira Code
主要是幾個原因

1. 我想試試 ligatures font
2. Fira Code 相較 JetBrains Mono 更細長點

大家可以嘗試看看自己喜歡哪一種字型

References:
1. Cascadia Code
2. Fira Code
3. JetBrains Mono
4. Font Switcher (VSCode extension)

2020/01/29

[自己的 Hackathon] L10 盃黑客松之即時開票系統 - 技術分享 (二) - 學習 Google Sheet API 與 Crawler

在上一篇依著微軟官方教學文件
學會了利用 Visual Studio Code 建立以及發佈 Azure Functions
接著就是要寫出我想要的 Crawler 以及即時更新 Google spreadsheet 的功能

流程簡圖

建立測試 Endpoint 來做 POC


因為每個部份我都沒有實際自己寫過
所以方便起見我建立了一個 HTTP trigger 的 Azure Function
在裡面寫一些 POC 的小片段
再把可行的部分搬移到對應的 Crawler 或是 Update Handler 中
我簡單盤點了一下我需要完成的幾項工作

T1. 從中選會網頁上爬到票數
T2. 將票數轉換成我定義好的 JSON 後,塞入 Azure Queue Storage 中
T3. 從 Azure Queue Storage 取出 JSON
T4. 依 JSON 中的對應票數,使用 Google Sheet API 填入 Google spreadsheet 對應的格子中

首先很快的利用 Azure Functions extension 建立好三個 Azure Functions
分別為

1. Timer trigger 的 Crawler
2. Azure Queue Storage trigger 的 Update Handler
3. HTTP trigger 的測試 Azure Function

最先完成的就是最簡單的 T2 與 T3
因為在教學文件中都有介紹到
唯一不同的就是要設計自己的 JSON 樣子而已
{
  "time": "1580121166",
  "votes" : {
    "president" : { "blue" : 1, "green" : 1 },
    "taipei3" : { "blue" : 1, "green" : 1 },
    "taipei4" : { "blue" : 1, "green" : 1 },
    "taipei5" : { "blue" : 1, "green" : 1 },
    "taichung3" : { "blue" : 1, "green" : 1 },
    "hualien" : { "blue" : 1, "green" : 1 }
  }
}


使用 Google Sheet API 填入對應票數


將 Crawler 與 Update Handler 串起後
下一件事情是學習怎麼在 Update Handler 中
用 Google Sheet API 去更新 spreadsheet
我是使用 pygsheets 這個 package
說明文件也算清楚
可以在 requirements.txt 中填入要使用的其他套件
在執行 debugger 的時候會自動用 pip install 幫你安裝

使用 pygsheets 套件前得先取得 Google API 的授權
我是使用 Service Account 的方法
要注意的就是 credentials.json 的檔案位置
一開始一直傳不對的路徑進去
導致卡關了一小段時間

學習怎麼寫 Crawler


我主要是看這個影片
[爬蟲實戰] 如何透過 Python 網路爬蟲 抓取並整理 2018 公投選舉資料?
非常仔細也非常詳盡
裡面介紹了兩個 packages, BeautifulSoup 與 pandas
我只需要用到 pandas 就好
就先用候選人簡歷的頁面練習
原則上是沒有遇到太大的問題
有錯誤的時候稍微再到 pandas 的官網查一下文件
或是利用 Google 都可以找到解答

利用條件式格式設定 highlight 第一名


我本來就會使用 RANK() 這個函式來排名
這次有兩個題目的排序需要預先處理,再餵入 RANK()
又很自以為的不想使用輔助欄 (就是先在其他格子內算出結果)
沒想到也搞了很久

ARRAYFORMULA() 應用


第一個是我要依 "絕對值" 由小到大排名
在這裡學到的一個公式是 ARRAYFORMULA()
ARRAYFORMULA() 可以想成本來 ABS() 這個函式只能計算一個格子的絕對值
套用 ARRAYFORMULA() 後,我們可以計算一個範圍內所有格子個別的絕對值
因此我們可以使用 ARRAYFORMULA() 的結果
再傳入 RANK() 的第二參數裡面使用
這樣我就不必使用一個輔助欄來先行計算絕對值再套用 RANK() 函式了

ARRAYFORMULA() 的結果


第二個是我要依 Max( |∆KMT|, |∆DPP| ) 由小到大排名
上圖中可以看到我用 ARRAYFORMULA() 先取得了一個二維的絕對值結果
下一步我需要把結果套入一個公式來取得兩欄中的最大值
這裡學到的是 QUERY() 這個公式
利用 QUERY() 我可以選出兩欄中最大的那一欄
不過 QUERY() 第二參數是類似 SQL 的語法
因此必須先做一次 TRANSPOSE() 把列與行對換
才能用 MAX() 語法取得最大值 (非常自找麻煩)

QUERY() 應用

最後就是再把結果 TRANSPOSE() 一次然後選出數字的那欄
就能餵到 RANK() 的第二參數中
非常囉嗦的方法,但是這樣就不必有輔助欄了

2020/01/18

[自己的 Hackathon] L10 盃黑客松之即時開票系統 - 技術分享 (一) - 學習 IDE 與 Azure Functions 基礎

這篇文章主要是我依著微軟官方文件
"使用 Visual Studio Code 在 Python 中建立和部署無伺服器 Azure Functions"
學習一些 Azure Functions 基礎的過程
分享我遇到的一些問題
如果你跟我一樣習慣英文介面的 Visual Studio Code
同樣的教學文件也有英文版 (較容易找到對應的 IDE 功能)

必要條件申請與安裝


文件中有三個前置要先準備好的東西
1. Azure 訂用帳戶 (Azure Subscription)
2. Azure Functions Core Tools
3. Visual Studio Code 以及對應的 extensions

首先最重要的當然是申請 Azure 帳號
新帳號在期限內能享有蠻多福利的
像是前三十天有 NTD 6,100 的額度可以使用
我多年前已經申請過了所以直接跳過這一步

新帳號可享的一些福利

再來就是安裝 Azure Functions Core Tools
先到 Node.js 下載頁面取得 v12.14.1 x64 的 Windows Installer 並安裝
接著依文件再輸入
npm install -g azure-functions-core-tools@3
文件中有提醒 "安裝 Node.js 時,請使用預設選項,「不要」 選取自動安裝必要工具的選項。"

最後就是安裝 Visual Studio Code
以及兩個對應的 extensions - Python extensionAzure Functions extension
我是使用 python 作為實作這次系統的程式語言
所以要記得安裝 python 3.7.5 64bit

執行 Azure Functions Core Tools 的錯誤

以上三個前置都準備好後
依著文件說明在 vscode 中登入你的 Azure 帳戶
然後在 vscode 裡的 Terminal 執行 func
這時候我遇到了一個問題

"因為這個系統上已停用指令碼執行,所以無法載入 XXXX\funcc.ps1 檔案。
  如需詳細資訊,請參閱 about_Execution_Policies,網址為 https:/go.microsoft.com/fwlink/?LinkID=135170。
"

幸好隨便 Google 就找到了解答
(錯誤訊息中的官方連結也是有解答, 但是找到的這篇比較直接)
用 administrator 權限執行 PowerShell 並執行
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
然後再執行一次 func 應該就可以看到 Azure Functions Core Tools 的執行畫面了

看到斗大的 Azure Functions Icon 就是成功啦

建立第一個使用 HTTP trigger 的 Azure Function


終於開始要寫程式啦
再次稱讚文件介紹的非常清楚
工具也是相當的好用
點幾下選一選就建立好了一個 HTTP trigger 的 Azure Function
啟用 debugger 也沒甚麼問題
第一個範例是你可以透過 GET 在 URL 裡傳一個 name 參數
Azure Function 則是把你傳入的名字字串回傳
文件也有附上用 curl 執行 POST 的指令
但是我使用 PowerShell 指令又遇到了問題
最後在多方搜尋嘗試下
修改成下面這段
$body = @{"name"="Visual Studio Code2"} | convertto-json
curl http://localhost:7071/api/HttpExample `
 -Headers @{"Content-Type"="application/json"} `
 -Method Post -Body $body
這樣就測試到 GET 與 POST 兩種方法了

但是在執行 debugger 練習測試的時候
一直有一個很惱人的問題
就是每當要停止 debug 的時候
整個 vscode 就會 hang 在那邊, 只能重開
幸好也有人反應這個問題
解決方式就是在 vscode 裡面把 azureFunctions.stopFuncTaskPostDebug 關掉
但是這會造成離開 debugger 後
本機上的 Azure Functions 仍會繼續執行 (等於是你只是 detach 該 process 而以)

發佈你的第一個 Azure Functions


也還是跟著文件做就好
唯一不同的是, 我會建議選擇 "Create New Function App in Azure... Advanced"
因為這個選項才能選擇 hosting plan 為 consumption plan
發佈好了就能直接用公開的 URL 來觸發你的 Azure Function

有三種計價方式

文件後面還有教怎麼使用 queue 來觸發 Azure Functions
基本上照著做都沒甚麼問題
做完這些就等於學會了怎麼用 vscode 來開發並佈署簡單的 Azure Functions 了

2020/01/13

[自己的 Hackathon] L10 盃黑客松之即時開票系統 - 過程 (不含技術介紹)

決定好了題目後
接下來就是要決定實作的系統樣貌跟需要用到的技術
好幾年前 (大約是林傑學長還在做微軟技術傳教士時)
我有用過 Azure Functions 做過一個整合 slack 與 trello 的 bot
當時是直接在 Azure 提供的網頁上寫 python 來達成
這次也是想利用 serverless 的技術試試看
所以設計了一個簡單的架構


流程簡圖

Crawler 跟 Update Handler 就用兩個 Azure Functions 實作
Queue 的部分使用 Azure Queue Storage

先來重新學習現代化的開發方式


這次想順便試試看目前使用 IDE 開發 Azure Functions 能做到多方便
所以先以 "使用 Visual Studio Code 在 Python 中建立和部署無伺服器 Azure Functions"
這篇微軟官方的教學文件開始
星期五晚上把小鬼們都弄去睡覺之後
就開始依著這篇文件一步步的學習
文件還算詳細
雖然還是有遇到一點點小問題
不過都能透過 Google 大神找到解決方法
走過整篇文件後
就可以學會幾件事情

1. 如何在本機上開發 Azure Functions 且啟動 local debugger
2. 如何建立 HTTP 觸發的 Azure Functions 並測試
3. 如何把資料用 Azure Functions 送到 Azure Queue Storage 中
4. 如何部屬本機開發好的 Azure Functions 到雲端上

我做完整個教學後就去睡覺了
準備明天早上起床後再新建立一個專案來做真正的系統

把系統雛型產生出來


一早八點起床
老婆出門上班而小鬼們還在睡
趁機加緊腳步把 Crawler, Update Handler 以及 Azure Queue Storage 都先建好
定義好要塞進 queue 的 JSON 樣子後
先把組合出 JSON 後塞入 queue
以及被 queue 觸發後取得 JSON 的部分做好

當然中間少不了排解小鬼們的紛爭
還有被女兒甩了門後進行諄諄教誨的時間
接著開始準備兩位少爺小姐的午餐
等到老婆回家後我趁隙出門投票
直到他們開始午睡
我再繼續推進我的進度

最後在投票截止前約半小時把基本的功能完成
Update Handler 可以依 JSON 的內容, 把票數填寫到對應的儲存格中
因為尚未開票所以沒有票數頁面可以爬
於是我用中選會網站的 "候選人簡歷" 確認我會使用 package 寫出可行的 Crawler
接著就是守在電腦前等待得票數頁面出現

有人投票日一早開 vscode 的嗎?

最刺激的時刻總會出現問題


我重新整理中選會網站到約下午四點十七分
開始出現得票數頁面了
馬上著手修改 Crawler 的部分
結果竟然遇到無法印出爬到的內容 (因為我想先用 print 看看爬到的內容是否正確)
搜尋了半天還是沒找到解法
靈機一動想說先印出爬到表格的欄數與行數
這樣我可以知道哪一張才是得票數表格
果然有用, 馬上針對我想知道的候選人票數做處理 (對不起宋杯杯)
確定爬到總統得票數且能透過 Azure Queue Storage 觸發 Update Handler
也寫了正確數字到 spreadsheet 後信心大增
就開始把剩下的區域立委做完
同時使用本機的方式先確定可以一直爬到最新票數
終於在五點半時按下 Deploy 按鈕送上雲端

一開始先以每一分鐘觸發一次的頻率觀察一下
前幾分鐘好像一切正常
結果出現了票數回朔的現象
只好馬上來 debug
用著不熟悉的 Azure 介面看 Application Insights
赫然發現我的本機仍在執行 Azure Functions
所以才會有被修改兩次的現象
但是關掉本機之後又發現不會取得最新的票數
Azure 雲端上的 Crawler 似乎會一直拿到一樣的內容
查了半天查不出結果
幸好透過 Application Insights 了解到原來在本機執行也可以
只好在出門前把雲端上的都關掉
開啟本機上的開發環境讓他自己跑了
萬幸的是在外面用手機看 spreadsheet
有一直在更新票數
才鬆了一口氣

最後收尾的 spreadsheet 排名


回到家後幫孩子們沐浴更衣完後
把最後 spreadsheet 上的結果表格
依照之前討論的勝利方式
利用條件式格式設定功能
將猜測最準的人 highlight 出來
這裡也學到了幾個 spreadsheet 公式
整個只有自己的 hackathon 就這樣告一段落
收穫真的很多

複雜的 spreadsheet 公式

2020/01/12

[自己的 Hackathon] L10 盃黑客松之即時開票系統 - 前言

這次 2020 總統立委選舉很激烈
我的某個朋友群中也開啟了一些對於選舉結果的猜測
起初是我很雞婆的幫忙整理了每個人的預測
一直到星期五的時候突發奇想
如果用 Google Sheet 來顯示結果以及大家預測的準不準
好像蠻有意思的
所以我花了點時間做了一個 spreadsheet
(已經去識別化, 請相關人士不要擔心)

spreadsheet 的樣子

簡單說明一下表格上的資訊
朋友們討論後決定一起來預測三個題目
1. 關注的區域立委當選與否
2. 兩大黨不分區的席次
3. 兩大黨總統的票數差
可以看到這些人關注的選區有五個

表的左邊我是安排放票數跟席次的資訊
右邊的上半部是放個別的預測
下面做了一個結果的表格
計算出各題大家的預測結果
1. 猜中的選區數 (多者得勝)
2. 猜測席次與實際席次的差, 少一席跟多一席為一樣的計分
    (這題相對複雜, 最後大家的共識是 Max( |∆KMT|, |∆DPP| ) 最小者勝
    請原諒我用類似數學的式子表示, 中文太差了 Orz)
3. 猜測票數差與實際票數差的落差 (絕對值小者得勝)

做好了後分享給朋友們
大家覺得蠻不錯的很好懂

一開始是跟大家說 "你們就自己更新票數吧"
後來下班開車回家的路上就在想

如果能夠爬中選會的開票結果網站
然後即時的填入票數到 spreadsheet 中
好像更有臨場感了

於是這小小個人黑克松就在我的內心裡慢慢萌芽