2014/09/11

OpenDataを活用した滋賀県(大津市)の観光スポットなどをナビゲーションするiOSアプリを作りました

オープンデータを活用した滋賀県(大津市)の観光スポットなどをナビゲーションするiOSアプリを作りました






アプリの概要

※オンライン状態でGPS機能をONにしてください。
機能一覧:
  • 市営駐車場
  • 観光名所
  • 社寺
  • 市営駐車場
  • 公衆トイレ
  • ホテル(小休憩用)
  • 花火大会当日用ゴミ箱 ※現在は花火大会終了しているため、使えません。
    上記スポットを選択するとマップにピンが立ちます。
  • 徒歩と車でどのくらい時間がかかるかの表示(デフォルトで車となっています)
  • テーブルのダブルタップで目的地への3Dルート案内
  • スポットのWeb案内
  • 目的地までの方角コンパスとリアルタイム距離表示、方位磁石付き

※マップにピンが立たない、表示されない時はしばらく経ってからアイテムを選択してください。

技術的な話


ホテル以外はすべて大津市のびわ湖大花火大会オープンデータを活用させてもらっています。
オープンデータとはなに?という詳細は割愛させてもらいますが、ざっくり言うと国や公共機関などが所有、管理するデータをアクセスしやすい、誰でも活用しやすい形に加工したデータです。そして、そのWeb上のデータをつなぐ(linkする)ことで、新しい価値を生み出そうとする取り組み、総称をLOD(Linked Open Data)というそうです。LODはWebの創始者Tim Berners-Leeが提唱しています。
最近テレビでも鯖江市などのオープンデータの活用事例が放映されていたり、今後かなりアツい分野であることは確かです。


公開されているオープンデータの取得方法

RDFで書かれたメタデータを検索するためのクエリ言語「SPARQL」を使用しています。

滋賀県のホテルリストの取得方法

ホテルリスト表示APIからObjective-cでスクレイピングしています。

スポットの画像取得

オープンデータで定義されていないものに関しては、
Google Image Search APIにて非同期で取得


最後に

京都でオープンデータはないのかと思い、調べたところ、オープンデータでの形式はないようです。

京都市 観光・モビリティ・防災 オープンデータ
https://kyoto.smartercity.jp/

全国の状況はというとこんなのを見つけました。

日本のオープンデータ都市数
http://fukuno.jig.jp/2013/opendatamap
2014/09/05日現在で45です。

まだまだ少ないといった印象ですね。

2014/09/06

SwiftからSPARQL利用

SwiftからSPARQLを利用するには

SPARQLは、エンドポイントと呼ばれるURIにGETリクエストでSPARQLクエリを投げると、json、xmlなど(指定可能)がレスポンスで返ってきます。

例えば、CocoaPodsでAFNetworkingを利用する場合
execQueryにSPARQLクエリを入れてください。

以下、びわ湖大花火大会に関するオープンデータ
        let manager :AFHTTPRequestOperationManager = AFHTTPRequestOperationManager()
        let url :String = "http://dl.opendata.shiga.jp/sparql"
        let sparql :String = execQuery
        
        let parameters :Dictionary = [
            "default-graph-uri" : "http://lod.opendata.shiga.jp/hanabi2014",
            "query"             : sparql,
            "format"            : "json",
        ]
        
        manager.requestSerializer = AFJSONRequestSerializer()
        manager.requestSerializer.setValue("application/sparql-results+json", forHTTPHeaderField: "Accept")
        manager.responseSerializer = AFHTTPResponseSerializer()
        let requestSuccess = {
            (operation :AFHTTPRequestOperation!, responseObject :AnyObject!) -> Void in
            NSLog("requestSuccess \(operation.responseString)")            
        }
        let requestFailure = {
            (operation :AFHTTPRequestOperation!, error :NSError!) -> Void in
            NSLog("requestFailure: \(error)")
        }
        
        manager.GET(url, parameters: parameters, success: requestSuccess, failure: requestFailure)


CC BY Yuichi Matsuoka / @you_matz

2014/09/05

Objective-CでのSPARQL利用

Objective-CからSPARQLを利用するには

SPARQLは、エンドポイントと呼ばれるURIにGETリクエストでSPARQLクエリを投げると、json、xmlなど(指定可能)がレスポンスで返ってきます。

例えば、大津市内の観光名所のデータ一覧を取得する場合は

  
prefix geo: <http://www.w3.org/2003/01/geo/wgs84_pos# ≷
prefix schema: <http://schema.org/ ≷
prefix place: <http://fp.yafjp.org/terms/place# ≷

select * where {
?uri geo:lat ?lat;
geo:long ?long;
rdfs:label ?label;
schema:address ?address;
schema:description ?description;
place:access ?access;
schema:url ?homepage.
filter(regex(str(?uri),"http://lod.opendata.shiga.jp/otsucity/tourist_attraction")).
}

Objective-CでのGETリクエスト送信部のサンプル
execQueryの部分にさきほどのSPARQLを突っ込む
  
    NSString *endpointurl = @"http://dl.opendata.shiga.jp/sparql?default-graph-uri=http%3A%2F%2Flod.opendata.shiga.jp%2Fhanabi2014&query=";
    // ここがポイント
    NSString *encodedText = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
                                                                                                  NULL,
                                                                                                  (__bridge CFStringRef)execQuery, //元の文字列
                                                                                                  NULL,
                                                                                                  CFSTR("!*'();:@&=+$,/?%#[]"),
                                                                                                  CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
    
    NSString *finalreq = [[endpointurl stringByAppendingString:encodedText] stringByAppendingString:@"&format=json"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:finalreq]];
    // Accept ヘッダ値は以下の指定に
    [request setValue:@"application/sparql-results+json" forHTTPHeaderField:@"Accept"];
    NSURLResponse *resp;
    NSError *error;
    NSData *resdata = [NSURLConnection sendSynchronousRequest:request returningResponse:&resp error:&error];    
 // jsonに変換
    NSMutableArray *jsonResponse = [NSJSONSerialization JSONObjectWithData:resdata
                                                                   options:kNilOptions
                                                                     error:nil];
    
    return [[jsonResponse valueForKey:@"results"] valueForKey:@"bindings"];


エンドポイントURLにエンコードしたクエリをひっつけて、
レスポンスの形式をapplication/sparql-results+jsonとし、GETリクエストを投げる。
 するとレスポンスはjsonで返ってくる。
jsonを配列に格納して、必要な部分を返り値として渡す。
エラー処理などはしていませんので、あくまで参考に。 

NSStringクラスの標準URLエンコードでは、対応しきれていない特殊な文字("!*'();:@&=+$,/?%#[]")がある。

  
//encoding
NSString *encodedText
     = [execQuery stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] 


CoreFoundationのCFURLCreateStringByAddingPercentEscapes()を使用
ARC環境では__bridge_transferを使用することでメモリリークを回避
  
 NSString *encodedText = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
                                                                                                  NULL,
                                                                                                  (__bridge CFStringRef)execQuery, //元の文字列
                                                                                                  NULL,
                                                                                                  CFSTR("!*'();:@&=+$,/?%#[]"),
                                                                                                  CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));



次はSwiftでやってみる

CC BY Yuichi Matsuoka / @you_matz

2014/08/24

La MusicaというYouTube Music Player作りました



一ヶ月以上前ですが、La MusicaというYouTube Player作りました。
音楽をずっと聞きっぱなしにできる作業用BGMが欲しかったので、開発しました。
音楽系のWebサービスのLast Fmが公開しているAPIを使えば、アーティストの情報など豊富な情報を取得できるAPIがあるので、比較的容易に開発できます。

使い方〜How To Use
アーティスト名を入れてplayボタンを押すだけ、
あとは自動的にアーティストの音楽がランキング順に流れます。

■一曲をリピートしたい時
・画面左リピートボタンを使用してください。

■Biographyの欄
アーティスト情報の表示

■Similarの欄
似ているアーティストの表示とリンククリックで、自動再生

■画面左Trend
人気アーティストTOP10のリンククリックで、自動再生

■取得する動画数を増やしたい
・デフォルトで20個に設定しているので、
増やしたいもしくは少なくしたい場合は、「set number」に
数字を入力してください。

静的なページのみの作成なので、GitHub pagesの使用で、無料です。
※アーティストから絞ったアマゾンの商品取得だけ、サーバサイドでGAEを使用してます。(GAEはリクエスト過多の場合、課金)

以下使用技術です。
(静的ページのみのホスティング)

FrontEnd
jsのMVWフレームワーク
■jQuery
■typeahead.js
オートコンプリート検索付きプルダウンリスト

WEB API
■Last fm
・曲のランキングの取得
・アーティスト情報の取得(類似アーティストなど)
・最新チャートのTOP10アーティスト取得

■YouTube Data API
・動画検索、取得(不要なものを除き、結果をランキング順にソート)
■YouTube JavaScript Player API
・動画プレイヤーの制御(連続自動再生、連続リピート)
■Amazon Product Advertising API 
・Amazonからアーティストのアルバム商品をひっぱってくる。

■GAE(Google App Engine)
GAEをAmazon Product Advertising APIを使うためだけに使用。
jsでAPI叩く方法が見当たらない(プラス、awsのkeyを公開したくないなどもろもろ)

ソースはGithubで公開してます。

La Musica Music Player

24時間好きな音楽聞き放題、あなたのミュージックライフを楽しませるツールです「Lamusica」 開発者インタビュー



2014/06/14

Swiftことはじめ、UIAlertView

iOSアプリ開発、新プログラミング言語Swift、
まずはUIAlertViewの表示から。

Swiftの場合
    @IBAction func showMessage(sender : AnyObject) {
        
        let alert = UIAlertView()
        alert.title = "Swiftでタイトル"
        alert.message = "SwiftでUIAlertViewを使ってメッセージ"
        alert.addButtonWithTitle("OK")
        alert.show()
    }
Objective-Cの場合
// 複数行で書くタイプ(1ボタンタイプ)
UIAlertView *alert = [[UIAlertView alloc] init];
alert.title = @"Objective-c title";
alert.message = @"完了しました";
[alert addButtonWithTitle:@"確認"];
[alert show];

2013/12/02

UNIXという考え方。その設計思想と哲学を読んだ

 The UNIX Philosophy
UNIXという考え方。
その設計思想と哲学。


普段Linuxを使用しているので、
読んでみました。

普段、使用しているツールの裏側の考え方について書いた本はほとんどないので、
新鮮です。


1.Small is beautiful.
小さいものは美しい。
小さい物同士であれば、組み合わせることが容易になる。

2.Make each program do one thing well.
ひとつのプログラムにはひとつのことをうまくやらせる。

3.Build a prototype as soon as possible.
できるだけ早く試作する。
すべてを完璧に設計してからでは遅い。

4.Choose portability over efficiency
効率より移植性を優先する

5.Store numerical data in flat ASCII files.
数値データはASCIIフラットファイルに保存する。

6.Use software leverage to your advantage.
ソフトウェアを梃子として使う

7.Use shell scripts to increase leverage and portability.
シェルスクリプトによって梃子の効果と移植性を高める

8.Avoid captive user interfaces.
過度の対話的インタフェースを避ける


9.Make every program a filter
すべてのプログラムをフィルタとして設計する

ソフトウェアの本質はデータを生成することではなく、
処理すること。


以下、重要度の低い小定理


1.Allow the user to tailor the environment.
ユーザごとに環境を好きに調整できるようにする

2.Make operating system kernels small anf lightweight.
オペレーティング・システムのカーネルを小さく、軽く。

3.Use lower case and keep it short.
小文字を使い、短く
4.Save trees.
森林を守る。

5.Silence is golden.
沈黙は金

6.Think parallel.
同時に考える
並列処理

7.The sum of the parts is greater than the whole.
部分の総和は全体よりも大きい

8.Look for the 90 percent solution.
90%の解を目指す

9.Worse is better.
劣る方が優れている。


10.Think hierarchically.
階層的に考える。


その通りと納得するものばかりでした。

UNIXという考え方―その設計思想と哲学









2013/11/10

テーブル定義書作成Script



テーブル定義書を一から書くのってめんどくさいなって思うことありますよね?
てことで、githubにあげました。
これでさくっと定義書作れます。
DBはMySQLです。

https://github.com/manchan/TableDefineScript


使い方

1.generate_document.sh
下記コマンドをコンソール上で実行
bash generate_document.sh DB名 > tableDefineDoc.html
root でパスワードなしで
※適宜書き換え必須
指定したDB名のテーブルすべてを
show full columns form $table 
2.mysql_db_document.sh
bash mysql_db_document.sh DB名
MYSQL_USERとMYSQL_PASSを適宜書き換えてください。

htmlでテーブル定義書が出力されます。
.xlsに変更でエクセル形式でも見れます。
cron定期実行も便利。