登山情報共有サイト ヤマレコ のAPIで遊んでみた。

[ヤマレコ](http://www.yamareco.com/)は、登山記録（山行記録）の共有サイトです。登山を趣味としている私もよく利用させてもらっています。気になってるあの山、あのルート、自分のスキルや装備で行けそうかな？なんてことを検討するのに非常に便利です。

この[ヤマレコが開発者向けにAPI](https://sites.google.com/site/apiforyamareco/)を提供していたので、遊んでみることにしました。今回はとりあえず入門編で、OAuthを必要としない機能のみ利用です。これだけでも記録や地名などのリストを取得できます。

ヤマレコには「拍手」という、FBでいう「いいね」のようなシステムがあります。山行記録を単に並べて表示するだけではあまりに芸がないので、「拍手」の多い順に表示してみました。

ユーザIDを入力して読み込みを押すと、山行記録が表示されます。ユーザID（ユーザ名ではなく）は、ユーザのプロフィールのページを開いてURLを確認すると知ることができます。

Google App Engineにデプロイしてみました。
http://1.shuetsu512-yamareco.appspot.com

リポジトリはこちらです。
https://github.com/shuetsu/yamareco_api

技術的に難しいことは何も行ってないんですが、いちおう簡単な解説。

まずはサーバ側。言語はJavaです。

APIとお話するために、以下のクラスを用意しておきます。今回の例ではGETメソッドしか使いません。

``` Util.java
public class Util {
	
	private static final String URL = "http://api.yamareco.com/api/v1/";
	
	public static String apiGet(String path){
		String ret = "";
		BufferedReader r = null;
		HttpURLConnection con = null;
		try {
		    URL url = new URL(URL + path);
		    con = (HttpURLConnection)url.openConnection();
		    r = new BufferedReader(new InputStreamReader(con.getInputStream()));
		    String l;
		    while ((l = r.readLine()) != null) {
		        ret += l;
		    }
		} catch (Exception e1) {
			ret = "{err:1}";
		} finally {
		    if (r != null){
		    	try{r.close();}catch(IOException e2){}
		    }
		    if (con != null){con.disconnect();}
		}
		return ret;
	}
}
```

今回利用したのは、ユーザ情報を取得する getUserInfo と、山行記録のリストを取得する getReclist です。それぞれユーザIDを渡します。具体的には以下のURLをGETします。

http://api.yamareco.com/api/v1/getUserInfo/(ユーザID)
http://api.yamareco.com/api/v1/getReclist/user/(ユーザID)

以下のサーブレットを用意しました。ヤマレコAPIから取得したjsonをそのままクライアントに返すだけの簡単なお仕事です。それぞれ /userinfo と /reclist というパスにマッピングしておきます。

``` UserInfoServlet.java
public class UserInfoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("application/json; charset=utf-8");
		PrintWriter w = resp.getWriter();
		w.println(Util.apiGet("getUserInfo/" + req.getParameter("uid")));
		w.close();
	}

}
```

``` ReclistServlet.java
public class ReclistServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("application/json; charset=utf-8");
		PrintWriter w = resp.getWriter();
		w.println(Util.apiGet("getReclist/user/" + req.getParameter("uid") + "/" + req.getParameter("page")));
		w.close();
	}
}
```

続いてクライアント側。普通にjquery使います。

読み込みボタンが押されると、まずはユーザ情報を取りに行きます。とりあえず入れてる 49432 は私(shuetsu)のユーザIDです。取得できたらユーザ名を表示します。

[ガイドライン](http://www.yamareco.com/modules/pico/index.php?content_id=58)によれば、山行記録を表示する場合は投稿者のユーザ名を併記すべし。とのことです。

``` index.html
ユーザID:
<input id="uid" type="text" value="49432"/>
<input type="button" value="読み込み" onclick="get_user_info($('#uid').val());"/>
```

``` example.js
function get_user_info(uid){
	$.ajax({
		dataType: 'json',
		url: "/userinfo",
		data: {uid: uid},
		cache: false,
		success: function(data){
			if (data.err == 0){
				$('#user_name').html(data.userinfo.uname + 'さんの記録');
				get_reclist(uid);
			}
		}
	});
}
```

最後に山行記録を取得して、ソートして、表示します。拍手数(cheer)に基づいてソートするために、sortメソッドに比較手続きを渡してます。

``` example.js
function get_reclist(uid){
	$('#result tbody *').remove();
	get_reclist_aux(uid, 1, []);
}

function get_reclist_aux(uid, page, reclist){
	$.ajax({
		dataType: 'json',
		url: "/reclist",
		data: {uid: uid, page: page},
		cache: false,
		success: function(data){
			if (data.err == 0){
				Array.prototype.push.apply(reclist, data.reclist);
			}
			if (page < 5){
				get_reclist_aux(uid, page + 1, reclist);
			}else{
				show_result(reclist);
			}
		}
	});
}

function show_result(reclist){
	reclist.sort(function(rec1, rec2){
		var c1 = Number(rec1.cheer);
		var c2 = Number(rec2.cheer);
		if (c1 < c2) return  1;
		if (c1 > c2) return -1;
		return 0;
	});
	for(var i = 0;i < reclist.length;i++){
		var rec = reclist[i];
		var r = '<tr>';
		r += '<td><img src="' + rec.thumb_url + '"/></td>';
		r += '<td><a href="' + rec.page_url + '" target="_blank">' + rec.place + '</a></td>';
		r += '<td>' + rec.start + '</td>';
		r += '<td>' + rec.cheer + '拍手</td>';
		r += '</tr>';
		$('#result tbody').append(r);
	}
}
```

次はOAuth認証が必要な機能についても試してみたいです。