大量地址轉換經緯度的方法

如果手上有一批地址資料需要顯示在地圖上,要先將這些資料轉換成經緯度才行。而中文地址轉換成經緯度,目前應該只有Gooe Map API做得到,我試過其他各家的API,例如MapQuest、ArcGPS、MapBox等,都不支援中文地址(這裡有詳細的Geocoder API清單)。

使用JavaScript Google Map API

Google May API提供了Geocoder的方法,以下是範例:

Google Map API使用API Key的話,會有一天2500個查詢的限制,若不使用API Key,則查詢沒有上限。根據Google官方文件的說法,這是為了舊版API的相容性。而這樣的設計這也算是個漏洞,如果要做大量的批次轉換,就不用給API Key。可是這種方式不允許短時間內大量的查詢,否則有些查詢會失敗。解決方法是,每個查詢間隔一秒(用setTimeout)。

以JavaScript來說,要寫成批次程式可以使用Node.JS。但Node.JS本身是非同步執行,也就是說,Function A還沒執行完畢,可能Function B就已經開始執行了。幸好Node.JS有不少流程控制的套件可以處理非同步的問題。比較著名的套件是q,這個套件實作了JavaScript Promise。我自己寫過之後覺得,用Node.JS寫批次的眉眉角角很多,如果熟悉Python的話,用Python來寫批次應該會比較合適。

批次轉換工具

如不想自己寫程式做批次查詢,網路上有兩個工具可以使用。

1. 我自己寫的Batch Geocoder小工具

這是用JavaScript寫的,沒有查詢筆數的限制。它是1秒查詢一筆資料,等於一小時只能產生3600筆,而且要開著瀏覽器等待,比較適合少量資料的查詢。

2. 內政部TGOS全國門牌地址定位服務

這個網站產生的經緯度比Google精確,可是需要上網申請帳號,個人帳戶的限制是,每天可批次查詢一萬次,機關及學校單位另可申請公司帳戶,每個月可查詢三十萬次,也可使用該網所提供站的即時API。


分類: ,

Homebrew作者的新公司是....

還記得六月份Homebrew作者到Google面試,結果被打臉的消息嗎?

Max Howell八月已經換工作了,現在是Apple的員工。也太強了吧!

Source: LinkedIn

分類:

[遊記] 多倫多 High Park Zoo

每個偉大城市都有一座獨一無二的公園,多倫多的公園叫做High Park,位於多倫多市區的西邊,這個公園種滿日本櫻花,每年三到五月會開滿櫻花。我們到的時間是五月,不巧上個冬季是多倫多少見的嚴酷寒冬,也間接影響了櫻花花期,那年的櫻花季節極短,花開的也不夠茂盛。



High Park公園內有一處小型的動物園,這裡不像多倫多動物園那麼有名氣,但也規劃的還不錯。我們是周一下午到達的,這裡平日沒什麼遊客,可以悠閒的隨意亂逛,裡頭的動物在亞洲並不常見,例如羊駝、美洲髦牛等。


用插圖方式介紹動物,頗具創意



多倫多也看得到羊駝,這裡是叫Llama,在紐西蘭是叫Alpaca。





High Park Zoo


分類: ,

微軟TechDays三大亮點

聽說上週是微軟TechDays 2015,在前公司工作時,連續參加了六年的TechDays。今年年初離職退隱之後,沒在用微軟的產品,對今年的Techday沒有多大興趣,索性就不報名參加了。之前去TechDays的報名費是公司出的,老實說,如果自己花錢,我會選擇去參加COSCUP

覺得這幾年參加完TechDays,沒有太大的收獲,就只是拿到一個不錯的大會背包,吃了一頓還不錯的午餐,以及拿了一堆沒用的廠商贈品而已。

Techday三大亮點

1. 講師陣容

因為認識其中幾位講師的關係,知道大部分的講師都是業界顧問,也有人在外面教課(或兼課),不過TechDays的講師陳容每年都大同小異是怎樣。

有些認真的講師,會準備了一堆demo和教材,不過TechDays不是上技術課程,準備艱深的教材,加上國際會議中心舒適的座位,底下的人都睡著了。然而也有很混的講師,我發現某位講師連續三年的課程內容都一樣,講師姓名就不說了,關鍵字「跨國公司DBA」。

2. 課程內容

微軟開發團隊導入Scrum之後,每年產品都有新功能推出。所以每個場次的課程內容,都不外乎是產品的新功能介紹,不過一直有新功能是要逼死誰。

TechDays是微軟的場子,當然是宣傳微軟自家的產品(名正言順的置入性行銷)。而且使用者還付費才能參加,多好!這就像是銀行舉辦的付費金融研討會,結果內容都是宣傳自家賣的金融商品。只能說,台灣微軟的行銷做的真不錯。

3. 大會背包

TechDays的大會背包還不錯,而且一年比一年好,比起其他研討會送的雜牌背包,TechDays的大會背包耐用又實用。很多人參加TechDays都是去拿背包的,以前還有同事第一天專程去拿背包後就回公司繼續上班。



對Techday 2015有興趣的朋友,可以等待微軟之後釋出video和投影片。如果等不及,也可以先看暗黑大的筆記:

[更新] TechDays 2015的課程影片及投影片已經發佈了。
https://channel9.msdn.com/Events/TechDays/TechDays-Taiwan-2015




分類:

讓專業的來,比較..安全!

在職場上,通常有人力不足的時候,老闆常會東拼西湊的把人力補齊,也不管這個人的專長是什麼,反正一個蘿蔔一個坑。設法把HeadCount補齊了,好辦事剩下的就是你們的事了。

所以工程師去補PM的位置,QA去寫程式, PM去做測試。專案團隊大風吹,大家做的都不是自己預期該做的工作。


會有這個感慨,是看到了前幾天的中職。棄投從打的陽耀勳,在球隊的投手被打爆的狀況下,上場把剩下的比賽投完。結果不小心投了觸身球,還把對方的球員打到受傷。

專業的事,讓不專業的來做,危險的是別人,讓專業的來,比較安全!

是說,林哲瑄大概也沒辦法打年底的十二強國際賽了,那麼中外野的位置誰來扛?該不會是陽耀勳吧!?



中職》林哲瑄挨陽耀勳球吻 左腳趾骨折形同報銷

分類:

Heroku Outage!

PaaS服務Heroku剛剛(9/20 18:00)掛了,機會難得,趁機觀摩一下人家的Incident Report是怎麼做的。

Heroku第一時間就把訊息公佈在https://status.heroku.com/,讓開發者瞭解狀態。這次的當機是service provider的問題,只有Development受影響(這裡的Development指的應該是免費用戶)。

這裡是說明處理狀態,每半小時會更新一次最新的處理狀態。

Heroku也在Support頁面貼上公告,大概是為了避免一堆人上去發Case吧。

使用SaaS / PaaS服務,仍然會有Service Down的風險,但至少廠商會主動把狀態公佈出來。另外還發現,Heroku在全球設置的兩處機房,美國和歐洲,歐洲的SLA近乎完美,比美國好太多了。



現已當機超過兩小時了,Production也當掉了,原來status頁面有時間軸

更新:從TNW看到的消息,這次Heroku當機的原因應該是AWS美東機房的DynamoDB掛了,從時間點上來看是吻合的。AWS這次的當機,也造成多個雲端服務掛點。





分類: ,

新北市垃圾車即時資訊

新北市政府提供的資訊源「新北市垃圾清運車輛所在位置」,只提供地址,沒有經緯度資訊,若要使用,只能自己在APP中用程式即時轉換,可是當資料量一多,APP的查詢時間就會非常久,很不方便。

我曾在新北市開放資料平台反應意見,希望他們可以提供垃圾車即時位置的經緯度,不過被拒絕了,理由是另一個資訊源「新北市垃圾車路線」已經提供了,但那資訊源不是垃圾車的即時資訊啊!即時資訊中的地址資料,想必是垃圾車上的GPS定位裝置,回傳的經緯度所轉換的,加上經緯度應該不困難吧。

既然被拒絕了,那就自幹吧!

我自己寫了一個批次程式,每十分鐘去抓新北市資訊源資料,把逐筆地址轉換成經緯度,再全部儲存回後台,讓我的APP可以查詢。概念很簡單,但實作上約莫花了一週,大部分的時間都在測試批次工具及平台。技術的部分,日後會逐一分享。以下先列出這次使用到的技術及平台:

  • 批次是用Node.JS寫的,寫到一半才發現Node.JS是非同步的,最後用了Promise才搞定執行順序,前後花了很多時間,早知道就用Python寫
  • 地址轉經緯度用Google Map API服務
  • 批次程式是放在Heroku,用Heroku Scheduler跑的,本來想用Parse Cloud寫的,可是太難用,寫到一半就放棄了,也試過Iron Worker,不過Iron Worker免費版一個月只有10小時。
目前先將串接好的資料放到網頁上,主要是用來作資料驗證,有興趣也可參考。之後會把資料整合到台北倒垃圾APP




分類: ,

[遊記] 多倫多 Casa Loma古堡

Casa Loma在多倫多市區的北邊。Casa Loma的主人是在十九世紀加拿大的富豪,因為他的妻子行動不便,不能去歐洲欣賞各地的建築精髓,索性自己在多倫多請最好的設計師幫他蓋歐式古堡,雖然城堡的歷史僅一百多年,跟歐洲古堡相比,略微遜色,但它畢竟是加拿大境內少數的真城堡。







門口的噴水池

進城堡內部要買票,大人是24加幣。如果不想入內,可在外面照相。

城堡內部裝潢超級豪華,有98間房間,用的建材傢俱也是極為奢華。可是在一次大戰時城堡主人破產了,最後用不到十分之一價格,把這座城堡還有裡面的藝術品賣掉。









分類: ,

[Android] SwipeRefreshLayout - Google的Pull-To-Refresh下拉更新套件

當手機APP上的資料需要被動更新時,目前的標準作法,是採用下拉更新的方式。就是由用戶的手指按住螢幕,向下滑動後放開。這個動作一般稱為 Pull To Refresh,有著形隨功能(Forms Follow Function) 的設計美學。

在 iOS 也有下拉更新的功能,但並非蘋果原創,目前是 Twitter 擁有這項專利。個人認為下拉更新是UX非常突破性的設計,記得在 2007 年左右,Android 當時是 1.6 版,UI 介面沒有像現在那沒多樣化,當時不知道是哪位工程師異想天開,在 APP 上做出了搖動更新的功能,就是借由搖動手機來更新資料。當時這樣的功能是滿有創意的,好多 APP 跟著倣效,所以那陣子時常看到在捷運上有人不斷晃動自己的手機,現在想起當時的情景,覺得還滿蠢的。

這篇要介紹的是Google官方的下拉更新套件 SwipeRefreshLayout,在 Google 還沒推出自家的下拉更新套件之前,GitHub 上已有很多第三方的下拉更新套件,不過大部分都已經不再維護了,因此這裡建議使用 Google 官方的 SwipeRefreshLayout。

要實作 SwipeRefreshLayout,需要引入 Android support v4 函式庫,函式庫的版本升级到 19.1 以上。下面是 Layout 的範例,在需要更新的控件最外層加上 SwipeRefreshLayout,然候它的child必須是可以滾動的view,例如ScrollView或者ListView。
Activity class必須實作(implements) SwipeRefreshLayout.OnRefreshListener
第10行的 setColorScheme 用來設置更新時 progress circle 的顏色,最多可設定四種顏色,多種顏色會循環播放。

還要覆寫 onRefresh 方法,將更新時要執行的程式寫在第22行。
第25行的數字,則表示下拉後延遲多久更新(單位是微秒)。 這是最後實作出來的效果,和Google Inbox的下拉更新一樣。


分類: ,

[JavaScript] 如何在網頁上顯示Parse.com的資料

首先要在HTML include Parse的JavaScript函式庫
http://www.parsecdn.com/js/parse-1.5.0.min.js
以下是JavaScript的範例程式,已經有註解說明,就不再解釋,請直接看程式。
//initialize
Parse.initialize('<your Application ID>', '<your JavaScript Key>');

//Parse object
var parseObject = Parse.Object.extend('<parse Object Data Name>');

// Create a query for places
var query = new Parse.Query(parseObject);
// User location
var userGeoPoint = new Parse.GeoPoint(25.0339031, 121.5645098);

// locations near user within 1 KM
query.withinKilometers('location', userGeoPoint, 1)

// Limit 100 rows
query.limit(100);

// Final list of objects
query.find({
  success: function(results) {

    //print results
    for (var i = 0; i < results.length; ++i) {

      //print address
      console.log(results[i].get('address'));

      //print latitude, longitude
      console.log(results[i].get('location').latitude + ',' + results[i].get('location').longitude));

    }

  },
  error: function(error) {
      console.log('Error: ' + error.code + ' ' + error.message);
  }
});

分類: ,

[遊記] 加拿大 密西沙加 Mississauga

密西沙加市在多倫多的西南邊,算是多倫多的衛星城市,如果用Google Map去瀏覽,會發現密西沙加大多是群聚的住宅區,很多住在密西沙加的居民是在多倫多工作,但因為房價的關係,選擇住在離多倫多約半小時車程的密西沙加市,有點類似台北和桃園的關係。不過往來多倫多和密西沙加市之間的高速公路,每到上下班時刻必定大塞車。


會到密西沙加,是因為有親戚住在這裡,因為美加行程沒有規畫的很好,從紐約北上多倫多算是臨時起意,結果只在加拿大停留四天,選擇住在親戚家,也可省下一筆住宿費。到達加拿大是在五月中旬,其實比較理想的時節是在秋天,可以賞楓,若停留久一點天,還可以北上蒙特婁和魁北克,看看不一樣的城市風光。

密西沙加市的住宅,大多是典型的美式獨棟House,有自己的後院,配有兩個車庫,幾乎家家戶戶都有兩台車,要外出採買,不像台北那麼方便,得開半小時的車到附近的mall,在北美如果沒車是寸步難行。

屋內格局常見於美劇,一樓是客廳和餐廳,二樓是臥房,地下室則是儲藏室。冬天會下雪,所以屋內有暖氣系統,但沒有冷氣,因為夏天不熱。多倫多地震和颱風都不常見,所以這裡的建材不是鋼筋混凝土,可能是輕鋼架和木板為主,缺點是隔音很差,到了晚上整個社區都很安靜,連狗叫聲都沒有,如果有夫妻吵架的聲音,一定聽得一清二楚。

以下的照片都是隨機在路邊照的,每間房子都非常夢幻,而且造型都不同,相同的是,都是兩層樓和兩個車庫。其實我有稍微去問了房價,不意外的,比台北市透天厝便宜!












分類: ,

[Android] ParseQuery複雜條件

最近有個需求是使用ParseQuery下複雜條件的查詢,原本以為辦不到,後來細讀官方文件,沒想到自己居然試出來了,就先筆記下來。

先介紹ParseQuery的條件式,

In

篩選多筆資料使用 whereContainedIn ,類似SQL的In
String[] names = {"Jonathan Walsh", "Dario Wunsch", "Shawn Simon"};
query.whereContainedIn("playerName", Arrays.asList(names));

And

ParseQuery並沒有特定的交集And方法,只要將兩個條件式擺在上下行,就視同交集。當然和其他程式語言一樣。例如下面的例子,以SQL語法來說,就是 age > 20 and age <=50

// Restricts to age <= 50
query.whereLessThanOrEqualTo("age", 50);

// Restricts to age > 20
query.whereGreaterThan("age", 20);

OR

OR(聯集)方法比較複雜,需要先個別建立單獨的查詢,再將全部的查詢加入List,最後用  ParseQuery.or() 方法產生聯集的效果。例如下面的例子,以SQL語法來說,就是
ParseQuery<object> query1 = ArrayItem.getQuery();
query1.whereEqualTo("age", 20);

ParseQuery<object> query2 = ArrayItem.getQuery();
query2.whereEqualTo("age", 30);

ParseQuery<object> query3 = ArrayItem.getQuery();
query3.whereEqualTo("age", 40);
                          
List<ParseQuery<object>> queries = new ArrayList<ParseQuery<object>>();
queries.add(query1);
queries.add(query2);
queries.add(query3);

ParseQuery finalQuery = ParseQuery.or(queries);
根據以上的介紹,我希望查詢的條件是(A and B) or (C and D) or (E and F),該如何下ParseQuery呢?答案如下,見程式的註解,基本上滿直覺的,實際使用起來效率也不差。
ParseQuery<object> query1 = ArrayItem.getQuery();
query1.whereEqualTo("age", 20); //A and
query1.whereEqualTo("gender", "M"); //B

ParseQuery<object> query2 = ArrayItem.getQuery();
query2.whereEqualTo("age", 30); //C and
query2.whereEqualTo("gender", "F"); //D

ParseQuery<object> query3 = ArrayItem.getQuery();
query3.whereEqualTo("age", 40); //E and
query3.whereEqualTo("gender", "F"); //F 
                      
List<ParseQuery<object>> queries = new ArrayList<arseQuery<object>>();
queries.add(query1); // (A and B) or
queries.add(query2); // (C and D) or
queries.add(query3); // (E and F)

ParseQuery finalQuery = ParseQuery.or(queries);

分類: ,

[自製APP] 台北丟垃圾

目前台北市的垃圾桶近3000個,換算後台北市每平方公里有9.27個行人垃圾桶,平均每1073位市民使用一個行人垃圾桶。這樣的行人垃圾桶數量不算多,因此走在台北街頭,有時候手上有垃圾,常會找不到垃圾桶,垃圾拿在手上又有點尷尬。感謝台北市環保局將垃圾桶標註地理位置資訊,並將此資料集公佈為開放資料,讓我利用這個資料寫了一個找垃圾桶的APP。

功能簡介

根據台北市行人垃圾桶定位資料,提供最近距離的垃圾桶位置,可載入Goole Map導航,帶你去找最近的垃圾桶。

功能描述

  • 列出附近的垃圾桶清單
  • 以地圖方式呈現目前所在位置與垃圾桶位置

資料來源

下載

Get it on Google Play

畫面截圖

開啟APP後,就直接列出最近距離的垃圾桶,當然手機的網路和定位服務要先開啟。

選取任一筆資料後,就直接帶出現在位置(藍色)和定位點(紅色)間的地圖。

如果不知道怎麼走,可按下工具列上方的導航按鈕,會開啟手機上的Google導航帶你以行人模式走過去。

預設的查詢範圍是一公里,顯示二十筆資料,畢竟是行人專用,再多好像也沒意義,不過從設定還是可以是需求變更查詢距離和筆數。

政令宣導

這件事很重要,但我只說一遍,「嚴禁投入家用垃圾,違者重罰新台幣6000元!」


[更新] 網頁版:http://bin.ccjeng.com




分類: ,

DevOps 技能樹

這是在上週去參加DevOps2015研討會時聽到的。因為DevOps工具么壽多,有人就用元素週期表的概念把這些工具整理出來。這也算是另一種資料視覺化的呈現吧。

Periodic Table of DevOps Tools


我發現這張表上少列了一些工具,列的完整的話,恐怕兩張元素週期表都不夠畫。本次DevOps2015大會幾乎每場都在介紹工具,和現行DevOps的趨勢一樣,工具一個接著一個的推出,學都學不完。

但個人認為,不要盲目追求工具,概念比工具重要,以BI(商業智慧)為例,BI工具何其多,懂得概念,強者用Excel也可以做出很棒的效果。同樣的,這些DevOps工具,多數只是自動化工具而已,替換成任一script語言都寫的出同樣的效果,重要的是,要瞭解這些工具背後的設計概念和使用時機。




分類:

[遊記] 多倫多 古釀酒廠區 Toronto Distillery Historic District

在英國殖民時,這裡曾經是北美最大的釀酒廠區,Gooderham & Worts 釀酒廠的舊址,多數建築採工業式歌德設計,是北美最大,保存最完好的維多利亞時代的工業建築群,裡頭仍保留著當時的釀酒設備。

古釀酒廠區在2003年被改造成一個曆史遺址區,開放給遊客參觀。包括「X戰警」在內的數百部電影是在此拍攝的。



裡面全是紅磚建築物,這些建築物被改裝成餐廳、藝術品店、和商場。





這是在加拿大相當有名的咖啡店 Balzac's Coffee,在古釀酒廠區的分店,內部陳設相當復古。




店內的Google街景

Toronto Distillery Historic District
55 Mill Street, Toronto, Ontario MSA 3C4, Canada (Downtown Toronto)


分類: ,

Copyright © Andy Cheng

Distributed By My Blogger Themes | Blogger Theme By NewBloggerThemes Up ↑