fonttool使用紀錄

簡介

fonttools是目前用在專案上的一個字型工具包,repo URL如下
https://github.com/fonttools/fonttools

安裝了該python module就可以使用裡面好幾種的字型工具,目前有用到的有以下:

pyftsubset
簡單說就是從字型中取出需要的字元生成一個較小的字型檔,主要為了節省空間,目前主要用在中日文語系這種漢字較多的語系,由於這類語系字型動輒都好幾mb,為了減少讀取時間是有其必要性
可以使用以下選項
--text-file : 將想要的字放在文字檔
--output-file : 選擇輸出檔案的路徑

ttx
一個轉換格式的工具,可以將字型轉換成一個xml格式的文件(.ttx)
ttx text.ttf
反之也可以再轉為其他的字型格式
ttx -o font.woff .\font.ttx

woff2支援

該工具支援轉換成woff2,由於使用了不同的壓縮方式會更小
要使用的話需要先安裝Brotli
但這個module安裝的時候需要安裝C++ compiler,可以按照連結依照自己的python版本,並且有相關安裝說明
https://wiki.python.org/moin/WindowsCompilers

文字剔除後的問題

目前看到有些地方會使用特定字元來做一些文字大小上的計算,故如果有用到這種方式需要將特定字元保留,以避免計算上的錯誤

https://stackoverflow.com/a/11688948
檢查字型是否已經讀取的一種作法
https://github.com/pixijs/pixi.js/blob/dev/packages/text/src/TextMetrics.ts#L652
pixi用於計算字型大小的做法

Godot最小產出測試

Godot

一個開源的遊戲引擎並具備編輯器,第一次知道這個遊戲引擎是大概2年前偶然發現的,會記錄這篇文章的原因主要是想知道這個引擎產出的release版遊戲大概最小可以到什麼程度,這在網頁遊戲來講還滿重要的。
以前曾經用unity產出幾個非常簡單的網頁遊戲大概都要4M起跳,其實跟一般html5的framework(如pixi.js)的所需檔案大小相差甚遠(V4.4.5 約403KB)。

初始系統安裝

  1. 安裝python 3.8
  2. 安裝scons
    python -m pip install scons
  3. 設定c/c++ compiler

下載 godot source code

一開始以為是要在遊戲專案下使用scons,會有以下訊息

scons: *** No SConstruct file found.
File “d:\dev\python\python38\lib\site-packages\SCons\Script\Main.py”, line 947, in _main

後來看了這篇才發現是要下載原始碼,在godot 原始碼目錄下使用

個人使用 3.2.3-stable
release 連結如下
https://github.com/godotengine/godot/releases/tag/3.2.3-stable
或者也可以使用 git clone tag 3.2.3-stable

下載結束後,可以執行scons platform=list

1
2
3
4
5
> scons platform=list
scons: Reading SConscript files ...
The following platforms are available:

windows

一開始只會有windows,scons會檢查是否有相關toolchain
https://godotengine.org/qa/30417/scons-build-only-has-windows-platform

設定c/c++ compiler

如果遇到下面的訊息

1
2
3
4
5
scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly
File "D:\godot\test\SConstruct", line 3, in <module>
ModuleNotFoundError: No module named 'glsl_builders':
File "D:\godot\test\SConstruct", line 15:
import glsl_builders

表示需要安裝VS compiler, 此時可參照下面網頁內容
https://wiki.python.org/moin/WindowsCompilers
我使用python 3.8 故照這一節處理

編譯web版

主要參照以下內容
https://docs.godotengine.org/en/stable/development/compiling/compiling_for_web.html

安裝emscripten
https://emscripten.org/docs/getting_started/downloads.html
參照這個連結,照著操作就可以
唯一要注意的點是每次要編譯前需要設定環境
只要執行sdk底下的emsdk_env.bat就可以

設定成功後輸入scons platform=list應該會多出一個新的選項

1
2
3
4
5
6
scons platform=list
scons: Reading SConscript files ...
The following platforms are available:

javascript
windows

看到javascript後可以輸入scons platform=javascript tools=no target=release -j 4開始編譯,如果編譯成功的話檔案會在godot_root/bin/godot.javascript.opt.zip。如果target=release_debug的話會是godot_root/bin/godot.javascript.opt.debug.zip,-j 4是使用多核編譯

根據這一節的內容,我們可以藉由關閉一些功能來減少產出的程式庫大小,其調整可以使用console的選項,但godot提供另一個方法,可以放一個custom.py檔案來設置選項,並且提供工具來生成這個檔案,以下是我使用的設置

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
# Generated using https://godot-build-options-generator.github.io

disable_3d = "yes"
optimize = "size"
disable_advanced_gui = "yes"
deprecated = "no"
module_arkit_enabled = "no"
module_bmp_enabled = "no"
module_bullet_enabled = "no"
module_camera_enabled = "no"
module_csg_enabled = "no"
module_dds_enabled = "no"
module_enet_enabled = "no"
module_etc_enabled = "no"
module_gdnative_enabled = "no"
module_gdnavigation_enabled = "no"
module_gdscript_enabled = "no"
module_gridmap_enabled = "no"
module_hdr_enabled = "no"
module_jpg_enabled = "no"
module_jsonrpc_enabled = "no"
module_mbedtls_enabled = "no"
module_mobile_vr_enabled = "no"
module_ogg_enabled = "no"
module_opensimplex_enabled = "no"
module_opus_enabled = "no"
module_regex_enabled = "no"
module_stb_vorbis_enabled = "no"
module_tga_enabled = "no"
module_theora_enabled = "no"
module_tinyexr_enabled = "no"
module_upnp_enabled = "no"
module_vorbis_enabled = "no"
module_webm_enabled = "no"
module_webp_enabled = "no"

應該是能關的都關了,唯一沒關的是Enable module: FreeType,關了之後我遇到編譯錯誤,所以就放棄了,這樣編譯的godot.wasm檔案大小是10051KB,沒有使用custom.py的檔案大小是14643KB

後記

這裡有一篇文章是以壓縮wasm來減少檔案大小,但其實應該Unity也是做得到,且壓縮後大小還是有其限度,故參考即可。

Jenkins使用筆記(Windows版)

安裝

  1. https://jenkins.io/download/ 下載windows Long-term Support version並安裝。
  2. 安裝完後,瀏覽器會自動開啟 http://localhost:8080/ ,此時可以看到Jenkins正在工作中。
  3. 之後Jenkins會要求你輸入一個在指定路徑檔案的密碼,路徑大概像是C:\Program Files (x86)\Jenkins\secrets\initialAdminPassword
  4. 密碼輸入後,Jenkins會要你安裝建議的plugin或者是選擇你自己需要的plugin,由於之後還可以再設定,所以可以先使用建議的就可以,之後的安裝會花幾分鐘的時間。
  5. 安裝完後,Jenkins會要求你輸入第一個管理者的資料,稍後可以再加入其他管理者的資料。
  6. Jenkins會要求輸入使用的URL,可以使用預設設定,安裝程序結束後可以再設定。
  7. 至此Jenkins已經設定完成,可以用左上角的 add job來增加建置job。

如何重啟或停止Jenkins服務

  • 透過 http://localhost:8080/restarthttp://localhost:8080/safeRestart 可以重啟jenkins服務。
    (jenkins_url)/safeRestart - 允許所有正在進行的jobs完成,新的jobs會被保持在queue中等到重啟完成後再執行。
    (jenkins_url)/restart - 強制重啟並不等待進行中的jobs完成。
  • 直接執行command, 加上參數如下
    ( jenkins_path)/jenkins.exe stop

    ‘install’ - install the service to Windows Service Controller
    ‘uninstall’ - uninstall the service
    ‘start’ - start the service (must be installed before)
    ‘stop’ - stop the service
    ‘restart’ - restart the service

  • 如果需要重開的理由是PATH的修改變動,必須要使用jenkins.exe來restart。

How to add SSH key

如果需要透過 ssh方式連接到git或者是建置過程需要使用到ssh,就需要先設定ssh key。

按下 Credentials.

按下 System.

按下 Global credentials (unrestricted).

按下 Add Credentials . 選擇 SSH Username with private key.
複製 SSH private key 的全部內容到 private key 欄位
(ssh private key 的預設路徑 : C:\Users\user_name\.ssh\id_rsa)
並輸入Username 與 passphrase (如果有的話).

Using ssh-agent in build process

https://plugins.jenkins.io/ssh-agent
如果建置過程需要使用到ssh-agent,可以安裝這個plugin來使用
在安裝之後,在建置環境中可以看到SSH agent選項,選取以設定ssh key

Using Slack notification

https://plugins.jenkins.io/slack
slack是一個企業用的通訊軟體,如果剛好公司使用了這個軟體而且需要通知建置結果,除了使用api方式來通知,也可以透過這個plugin來處理。

我覺得好用的plugin

使用 BitBucket PullRequest API

前言

由於目前公司專案數量大約有幾十個
有一些共同的修正因為設計關係需要對所有專案都進行類似的修改
這類作業舉例來說會是一些換圖或者是一些檔案調整
目前大多是自己寫腳本來處理
流程一開始如下
開branch->修改->commit->push->提PR
由於一開始提PR這個流程沒有自動化
所以還是需要一些人工去處理

後來將流程改成
主branch修改->commit->push
這樣的風險在於腳本萬一處理有問題的話沒有檢查處理結果的機會
後來覺得應該還是要走PR的流程
所以需要將PR自動化

App password

這是一個需要預先準備的東西
在bitbucket settings中可以找到這個選項
因為有的api需要你輸入使用username以及password
(官方給的curl範例是-u選項
postman中會是在Authorization分頁中使用Basic Auth)
此處的password是指App password
可以針對不同的權限需求使用不同的密碼

使用PR API需要的權限
Team membership R
Pull requests R/W

curl 轉 python

由於官方給的範例主要是curl
我自己用的是python
可以用以下網頁轉換
https://curl.trillworks.com/

如果用postman也會有提供轉換功能

API

前置作業: 取得使用者資訊(uuid)

主要用於設定reviewer
在使用PR API時會需要對方的uuid

api page:
https://developer.atlassian.com/bitbucket/api/2/reference/resource/users/%7Busername%7D

使用範例:
https://api.bitbucket.org/2.0/users/hsienwei

response 範例:

1
{"display_name": "hsienwei hsiang", "uuid": "{c56de9fd-b17b-4fd0-9d42-89a114ba839c}", "links": {"hooks": {"href": "https://api.bitbucket.org/2.0/users/%7Bc56de9fd-b17b-4fd0-9d42-89a114ba839c%7D/hooks"}, "self": {"href": "https://api.bitbucket.org/2.0/users/%7Bc56de9fd-b17b-4fd0-9d42-89a114ba839c%7D"}, "repositories": {"href": "https://api.bitbucket.org/2.0/repositories/%7Bc56de9fd-b17b-4fd0-9d42-89a114ba839c%7D"}, "html": {"href": "https://bitbucket.org/%7Bc56de9fd-b17b-4fd0-9d42-89a114ba839c%7D/"}, "avatar": {"href": "https://secure.gravatar.com/avatar/e75de8273492ae27638a55f7effc2f37?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FHH-6.png"}, "snippets": {"href": "https://api.bitbucket.org/2.0/snippets/%7Bc56de9fd-b17b-4fd0-9d42-89a114ba839c%7D"}}, "nickname": "hsienwei", "created_on": "2013-12-19T07:57:15.653135+00:00", "is_staff": false, "account_status": "active", "type": "user", "account_id": "557058:43f113de-285b-40cd-8271-e4a9e28f7331"}

這裡有一點需要注意,如果要使用uuid需要連左右大括弧一起使用,如上面範例的{c56de9fd-b17b-4fd0-9d42-89a114ba839c}

前置作業: 取得repo slug

一般來講repo slug就觀察來說應該就是你在網頁上看到的名稱,所以不太需要用API來看,但這裡有一個方法可以讓你看到指定team/user的所有repo資訊
api page:
https://developer.atlassian.com/bitbucket/api/2/reference/resource/teams/%7Busername%7D/repositories
使用範例:
https://api.bitbucket.org/2.0/repositories/hsienwei

需要使用username跟password才能取到private的資訊

如數量較多會分多頁顯示
會有幾個欄位提供如

Pull Request API

api page:
https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Busername%7D/%7Brepo_slug%7D/pullrequests#post

簡易python範例

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
import requests
import json

headers = {
'Content-Type': 'application/json',
}

data = {
'title': 'Just test',
'source':
{
'branch':
{
'name': 'source-branch-name'
}
},
'destination':
{
'branch':
{
'name': 'destination-branch-name'
}
},
'reviewers': [
{
'uuid': '{c56de9fd-b17b-4fd0-9d42-89a114ba839c}'
}
],
'description': 'aaa',
'close_source_branch': True
}


data_str = json.dumps(data)

response = requests.request("POST", 'https://api.bitbucket.org/2.0/repositories/username/reposlug/pullrequests'
, headers=headers, data=data_str, auth=('username', 'password'))

print(response.text)

這裡需要給的資料大概就幾個

  • title : PR的標題
  • source > branch : 來源分支
  • destination > branch : 目標分支
  • reviewers : 這裡填的是reviewer的uuid
  • description : 該PR的說明內容
  • close_source_branch : 合併後是否關閉該分支

AWS Lambda + LineBot

這篇主要紀錄一下之前寫的一個小玩具
主要是分為兩個部分

  • 使用Python + selenium 爬Ptt網頁版的資料並儲存在 AWS DynamoDB
  • 使用LintBot api加上AWS lambda回應上一步存在DynamoDB中的資料

第一部分是Python + selenium 爬Ptt網頁版的資料並儲存在 AWS DynamoDB

這裡主要是改以前寫的一個爬蟲程式, 以前寫的時候那時用的是python2.7版本並使用Mechanize 與 BeautifulSoup, 最近把它改成python3以及selenium連結, 目前還會有一些舊的程式碼在裡面。

程式可以指定要對哪個版來爬資料, 並可以指定要幾小時內的資料, 目前針對推文數高於一定程度以上的文章,另外使用FB API去取該連結的互動狀況, 用該資料簡單去算一個分數(可以在下面的測試結果畫面看到)用來作為熱門文章的排序, 這個數字的好處是可以看到實際在FB的熱門狀況, 因為有時候PTT推文數高的文章不一定是值得分享的文章, 也有可能是閒聊文。

另一part是將得到的資料寫進 AWS 的DynamoDB當中, 程式碼在這,會使用DynamoDB的原因主要是因為我的AWS 免費已經過期了, 所以我選擇使用目前還是有免費方案的DynamoDB。

主要使用了兩張表, 一張是索引, 主要紀錄各個板對應到另一張表的資料ID,另一張表就是爬下來的資料,以版名以及爬資料的時間當作ID來儲存。


第二部分是使用LintBot api加上AWS lambda回應上一步存在DynamoDB中的資料

會使用lambda其實是一個湊巧, 一開始本來是要開一個EC2加上Nodejs或Python+flask來回應linebot webhook, 但是想一想我已經沒有免費Tier了, 作為一個小玩具成本有點高, 後來在查資料的時候看到這篇文章, 覺得這樣server less的架構成本低, 又不需要一直開著, 也可以使用API Gateway來開一個https的api當作webhook。

這裡當初在做的時候本來要讓linebot在資料有更新時自動使用push來通知使用者, 但是由於push功能需要付費, 所以就作罷了。


下面就是成果
LineBot QRCode
可以加入這個LineBot來測試

以下是測試結果畫面
第一張圖, 隨便打幾個字可以得到目前有資料的版名
Imgur

第二張圖, 輸入一個有資料的版名後, 可以得到爬蟲爬到的資料, 標題後是其分數
Imgur