2016年12月31日 星期六

[Go] 利用goquery + otto來分析網頁

Please check full content on Le murmure de Julian http://ift.tt/2itmTNB
via IFTTT

2016年12月29日 星期四

[Android] Retrofit + Protobuf + Wire

Please check full content on Le murmure de Julian http://ift.tt/2iHB3XW
via IFTTT

2016年12月27日 星期二

2016年11月30日 星期三

2016年11月4日 星期五

2016年11月1日 星期二

2016年10月21日 星期五

2016年10月18日 星期二

2016年10月17日 星期一

2016年10月4日 星期二

2016年9月27日 星期二

使用AWS lambda和Github來提供中華職棒賽程資料

不知不覺的突然就多出了兩天颱風假, 這颱風實在很威, 乒乒乓乓的, 不過, 也沒做什麼, 時間就快過完了, 現在才想到, 還是來寫點什麼, 嚴格說來這些東西並不完全是颱風假時弄的, 只是拖得有點久

起因是, 之前(很久…追朔到去年)想寫個App, 需要用到中華職棒賽程的資料, 拖了很久一直沒真的去做, 斷斷續續的, 最近才先把資料這部分補齊, 首先需求是:

  1. 當月之後的賽程資料, 但中華職棒並沒有API, 只有(很爛)的網頁, 因此資料勢必得從網頁去解析
  2. 由Client app直接去解析html, 會比較麻煩(如果網站更新了, 就要更新App), 不是那麼可行
  3. 不想花錢(或不想花太多錢)弄一個server, 更不用說還要考慮Scaling

而賽程表這樣的資料的特性則是:

  1. 球季是3~10月
  2. 資料內容除週一(休賽)外, 幾乎每天都會變, 但不會一兩個小時或幾分鐘就變一次
  3. 變動的內容可能是:
    1. 比賽結束, 比數有更新
    2. 延賽或停賽
  4. 一個月才幾十場比賽而已, 基本上不太需要有search或query的功能, 依據月份分類也就足夠了

因此我採用的做法是:

  1. 利用AWS lambda定時解析中華職棒網站的資料
  2. 資料以json格式存在github (使用Github api)
  3. Client透過CDN去要這些json的raw content

賽程解析

這部分我是用Go + Goquery來寫的, source code在這邊: cpblschedule, 這code沒啥整理過, 光解析這堆亂七八糟的html就夠頭痛囉, 就沒啥整理

我做成了一個package, 因此要使用可用下列指令先安裝:

go get -u http://ift.tt/2d4uMIC

裡面也很簡單就一個function而已, 因此要使用可以參考:

import "http://ift.tt/2d4uMIC"

func main() {
        matches, err := cpblschedule.ParseCPBLSchedule(year, month)
    ....
}

AWS Lambda

這邊就不介紹這東西是什麼了, 網路上文章一大堆, 基本上他是AWS一個severless的解決方案(這算廣告詞吧), 會使用這個的原因有二:

  1. 依我的用量應該是免費(事實證明, 其實還是要花點錢, 我忘了算網路傳輸的費用了, 不過這不多)
  2. 可以用Cloud watch排程觸發

不過有個小問題

**他不支援Go!!!!!**

而我上面那個解析的東東是go寫的, 那不就寫心酸的

所幸還有別的辦法,就是把程式編譯成執行檔, 然後用nodejs去包裝它, 不過這有點煩瑣, 所幸還有工具

apex, 這是讓你更簡單的去建立lambda function的工具, 而且他正好也可以幫你簡單做好上面所說的包裝

安裝及使用就看文件吧, 不特別說了, 但要如何用go寫一個lambda function handle呢?以下是範例:

import (
        "encoding/json"
        "http://ift.tt/2az06sB"
)
func main() {
        apex.HandleFunc(func(event json.RawMessage, ctx *apex.Context) (interface{}, error) {
                dosomething()
                return nil, nil
        })
}

Github as API source

資料既然變動不頻繁, 就用lambda定期產生然後把結果放到Github上就可了

Github API的Go的實做是Google放出來的go-github, 文件還蠻眼花撩亂的, 不過在這應用需要的API不多:

  1. client.Repositories.GetContents - 取得內容
  2. client.Repositories.CreateFile - 創立一個新檔
  3. client.Repositories.UpdateFile - 更新某個檔

之所以需要1的原因是要確認檔案是不是已經在repository裡面了, 如果沒有就用create, 如果有就拿SHA hash去更新內容

GetContents會把檔案內容一併給抓回來, 這可以用來在更新檔案前先比較, 如果不比較, 就算沒更動, API也會新增一個新的commit, 為了避免不要太誇張, 還是先比較一下好了

那之後client怎樣存取這些資料? 找到檔案, 選取raw就可以知道raw的url了, client每次就抓這個URL就好, 但為了避免過量地request湧到github, 因此透過一個CDN來存取可能會好一點

這時候就可以用RawGit, 這邊透過MaxCDN, 讓你可以去存取Github上的raw content, 而你的檔案的網址會是像這樣:

http://ift.tt/2d4vhm7

大致上就這樣



from Le murmure de Julian http://ift.tt/2dxgYCa
via IFTTT

2016年8月31日 星期三

[Blog] 替Jekyll的markdown加上簡易流程圖功能

對一個developer的blog來說, 流程圖似乎是蠻需要的, 比較能夠清楚來解釋一些東西, 但每個東西都轉圖檔還蠻麻煩的, 下面介紹一個有用的Jekyll plugin, 可以做到像下面這樣的效果:

第一例

graph TD; A-->B; A-->C; B-->D; C-->D;

第二例

sequenceDiagram participant John participant Alice Alice->>John: Hello John, how are you? John-->>Alice: Great!

這是利用一個叫做Jekyll-mermaid 來達成的

而這plugin其實也沒做很多事, 它是包裝了mermaid這個工具, 而mermaid這工具他是利用了ds.js來讓你用很簡單的方式來繪製流程, 以上面兩個例子為例

第一例

graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;

第二例

sequenceDiagram
    participant John
    participant Alice
    Alice->>John: Hello John, how are you?
    John-->>Alice: Great!

所以你在markdown裡面只要加上

{ % mermaid % }
sequenceDiagram
    participant John
    participant Alice
    Alice->>John: Hello John, how are you?
    John-->>Alice: Great!
{ % endmermaid % }

他就會幫你render出相關的流程了

安裝方法

這邊以我自己blog的安裝方法來說明

  1. 把jekyll-mermaid.rb放到_plugins目錄去
  2. 在_config.yml加上 (這邊以6.0.0的mermaid為例):
mermaid:
  src: 'http://ift.tt/2c49O8u'

  1. 還要在head.html加上css (要配合版面顏色), 可以用這個 : http://ift.tt/2ce9Blg


from Le murmure de Julian http://ift.tt/2c49o2a
via IFTTT

2016年8月17日 星期三

[筆記]製作自己的Icon font

承續上篇的用icon font來製作圖示, 之前所提到的都是利用現成的icon font, 但似乎大部分的icon font都沒有像material icon有支援ligatures, 沒支援的話, 在xcode裡面就無法像上一篇一樣, 直接在UI designer顯示對應的圖示, 另外如果需要使用自己的圖示呢?其實是有方法用SVG圖檔來製作自己的icon font的, 這篇就來介紹兩種用SVG圖檔製作一個有ligatures支援的字型檔

grunt-webfont

第一個方法就是利用grunt-webfont, Grunt是一個前端常用的建構工具, 而grunt-webfont是一個用來產生字型的task

安裝相關工具

由於需要使用Grunt, node.js是必須的, 另外由於需要使用到fontforge, 所以python也是必須的, 雖然說grunt-webfont也可以純nodejs的module來產生字型, 但那並無法支援ligatures, 所以fontforge是一定需要的

npm i grunt --global來安裝grunt

製作字型
  1. 建立一個空的目錄
  2. 在這個目錄執行npm init來產生package.json
  3. npm i grunt-webfont --save來安裝grunt-webfont並且把這個dependency 加到package.json
  4. 建立一個svg子目錄(目錄名稱隨你高興, 這邊以svg當例子), 把所有圖示的svg檔案全部放到這目錄去
  5. 建立Gruntfile.js , 這檔案就像是Makefile, 或像是build.gradle這樣的角色, 內容就像下面
module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    webfont: {
        icons: {
                src: 'svg/*.svg',
                dest: 'build/fonts',
                options: {
                        engine: 'fontforge',
                        htmlDemo: true,
                        fontHeight: 96,
                        normalize: false,
                        ascent: 84,
                        descent: 12,
                        font: 'octicon',
                        fontFamilyName: 'octicon',
                        types: 'ttf',
                        ligatures: true,
                        startCodepoint: 0xF101
                    }
                }
    },
    clean: [
        'build/fonts/*'
      ]
  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-webfont');
  grunt.registerTask('font', ['clean', 'webfont']);
  grunt.registerTask('default', [ 'font']);
};

這邊最主要也最重要的task就是webfont這個, 這裡面src是svg檔的目錄, dest是字型輸出的目錄, engine的部分指名fontforge, ligatures設定必須要是true(產生的字型的ligature的名字其實就是沿用svg的檔名)

建立好這個檔後執行grunt即可

icomoon

上面的方法還是有點麻煩, 蠻手動的, 還有一個更方便的工具就是icomoon, 這東西方便更多, 它是一個相當強大的工具

Icomoon

從畫面上看, 它其實很簡單操作, 選定你所需要的圖示後, 按右下角的Generate Font即可, 除了你可以自己import自己的svg檔案外, 它也提供很多付費跟免費的圖示供選用:

Icomoon

按下Generate Font後, 並不會馬上讓你下載字型回家, 它會先讓你檢視字型將會包含的圖示, 這邊有件事很重要, 左上角有個fi圖示(參照下圖), 按下去後, 下面的圖示下面會多一個fi的欄位, 這就是讓你設定這些圖示的ligature的, 如果需要一個有支援ligature的字型, 就需要去設定這邊

Icomoon

所有都沒問題後按下右下角的Download就沒問題了



from Le murmure de Julian http://ift.tt/2bBpZvO
via IFTTT

2016年8月4日 星期四

[iOS開發筆記] 使用Icon font來節省圖示空間

寫App有一個讓人頭痛的是App大小的問題, 而這大小有部分是由App裡面所用的圖所貢獻, 為了減少這部份消耗掉的資源, 不管是用較大壓縮率的格式來壓縮圖檔, 還是其他, 大家都想盡辦法想解決這問題, 現在由於平面化的UI設計, 使得又有不錯的方法來解決這問題, 平面化UI設計的特色是大部分的圖檔都是單色而非五顏六色, 這使得用向量圖, 甚至用字型來解決這問題變得可行

免費的圖標字型(icon font)

把所有的向量圖示變成字型檔可以節省不少空間, 以流行的Font Awesome 來說, 它包含了634個圖標, 卻只佔了153KB, 這在以往可能是不到十個圖標的檔案就會達到的大小, 相較之下節省了不少空間, 像這樣開放的圖示字型, 可以找到不少:

  • Font Awesome : 蠻流行的一個開放icon組, 提供了ttf, woff等字型檔格式
  • Google material icons : Google開放源碼的免費icon組, 它不只提供Android, iOS可使用的圖檔外, 也提供了字型檔的部分, 而且它的字型檔支援了Ligatures (後面會再提到它好用的地方),這也使得它比Font Awesome來的好用
  • Weather Icons : 顧名思義, 這提供了222個可以用於表示天氣的icons, 不過對於風向的表示的部分, 它是用同一個圖示只是在web上利用css旋轉來顯示不同方向的風, 這一點應用到App上的話, 我是還沒找到比較適合表達的方式
  • Octicons : 由GitHub開源出來的圖標字型, 圖標不多, 但自己新增應該蠻方便的(自己增加svg檔用grunt去build)

除了這些之外, 應該還可以找到不少免費的圖標字型(icon font)可以用, IconFontKit這邊就列了不少(它也整合了)可用的圖標字型

使用這些, 除了可以節省app的大小, 也可以省下不少設計圖標的時間, 但也不是沒缺點, 因為是字型的關係, 它每一個icon都是對應到一個unicode字元, 這字元大多數跟icon的形狀沒關係, 也就不是那麼好對應, 通常都要查一下對照表找出字元碼

利用現成的framework整合

要在iOS上使用這些圖標字型(icon font)的方式好幾種,寫程式去load字型是一種, 當然就有不少大德, 寫好包裝可以讓你用cocoapods或是cathage直接引入, 這邊有幾個不錯的:

用這些現成的framework的好處是, 一來減去自己手動包裝字型進app的複雜度, 二來是, 這些已經幫你定義好一些對應圖標的常數, 讓你用比較方便的方式而不是記憶unicode字元來對應這些圖標

但它也是有缺點的, 大部分這些的作法都是runtime才去載入跟註冊字型, 因此你必須是在程式內設定你的UILabel, UIButton的字型, 無法事先就在Interface Builder做預覽, 所以個人比較喜歡的方式就是自己動手來

手動在xcode上使用自訂字型

自己手動加的好處就是, Interface Builder上就可以套用, 直接就可以看到結果, 但就是稍微繁瑣了一點

Interface Builder直接看結果

首先, 要把字型檔拖入你的Project裡面:

ttf files in project

接著打開Info.plist, 加上一個新的項目叫做“Fonts provided by application”

這個是一個陣列(Array), 它的內容就是你要加入的字型檔檔名, 把你要加的每一個都列進去

Info.plist

接著, 在Interface Builder裡你所要使用icon font的地方, 比如說UILabel設定你的字型, 原本的字型是設定為“System”, 把它改成“Custom”, 並選定你所需要的字型名稱, 例如FontAwesome, 要注意的是, 字型名稱不一定等同於你字型檔的名字:

Interface builder

Interface builder

接下來在Text的部分輸入這個圖示的代表的Unicode字元就好, 不是Unicode碼, 而是那個字元本身, 這挺不方便的, 可能用copy paste的才有辦法, 這是這個方法最大的缺點

這問題還是有方法克服, 這也就是前面為何提到會比較推薦使用Google material icons而不是Font Awesome , 這原因就是Ligatures

Ligatures

Ligatures是一個字型上蠻方便的特色的, 關於Ligatures可以先看一下這篇, 這是在Google material icons提到的一篇文章:

The Era of Symbol Fonts

剛剛提到的一個很大的缺點是, 你要知道圖示對應的Unicode碼才可以在你的UI上顯示你想要的圖示, 這相當不方便, 尤其那些Unicode碼可能根本完全不代表任何意義

比較人性點的作法是當你想要一個圖示代表藍芽, 用bluetooth就可以找到對應圖示, 而Ligatures就是一個這樣的存在

我們先來看看, 如果使用沒有而Ligatures的FontAwesome, 你在Text打上“Contacts”會是怎樣一個情形?

Ligatures1

它會直接一字不漏的呈現“Contacts”,這還是因為FontAwesome有包含原本英數字字型在裡面, 有些其他的自行更慘, 根本就是一片白

讓我們再看看用Google material icons的字型,同樣的東西會有什麼結果

Ligatures2

因為這個字型有支援Ligatures, 所以在這邊contacts就會被直接代換成它對應的圖示了, 我們就不用寄那種完全看不懂的unicode碼了

但大部分的字型其實也都沒有, 所以自訂字型該怎做?那就留待之後研究了



from Le murmure de Julian http://ift.tt/2aVJ1ya
via IFTTT

2016年7月5日 星期二

[iOS開發筆記] 模糊背景

去年為了參加WWDC, 開始練了Swift, 寫了兩個library, 不過好像一直都沒寫過完整的App, 連UI好像都沒真的去刻過(去年寫的東西跟UI比較無關), 因此最近利用了一些時間開始了個side project, 做side project就常常會把時間花在一些枝微末節的地方, 比如說, 為了做一個像Android那樣的Floating action button, 去找來一個現成的3rd party lib - yoavlt/LiquidFloatingActionButton , 那個像水珠一樣突出去的效果, 我還蠻愛的:

但缺點是, 後面缺一個擋住背景元件的, 以致於要去點伸上來的小按鈕容易誤按後面的元件, 因此就想自己改一個後面多一個overlay的版本, 當然也不想隨便貼一張白白的就交差, 起碼要像這樣:

這邊不是單純蓋一個深色半透明的背景而已, 還需要作一點模糊的部分

在iOS上(iOS8 之後), 作這樣的東西很簡單, 只要利用UIVisualEffectViewUIBlurEffect這兩個東西, 寫法很簡單:

    let blurEffect = UIBlurEffect(style: .Dark)
    let uiEffectView = UIVisualEffectView(effect: blurEffect)
    uiEffectView.frame = overlayView.bounds
    overlayView.addSubview(uiEffectView)

UIBlurEffect有三種樣式, Dark, Light, 和ExtraLight, 上面的範例是Dark, 蠻適合用在這地方的, 利用這個方法就可以不用自己擷取screenshot再算模糊化了



from Le murmure de Julian http://ift.tt/29fvPOb
via IFTTT