2014年2月20日木曜日
タイトル変更とドメイン設定しました
2014年2月17日月曜日
Top Coder SRM 609 Level3 おさらい
今回はGumiとIaとMayuというボーカロイドが音楽アルバムを作りますという若干Geekyなお題でした。以下のような入力値が与えられた時に、すべての曲が必ず一名以上に歌われるようなアルバムのパターンは何種類あるかという問題です(一つの曲を複数人で歌うのはOK)。
入力値(すべて1から50までの整数)
- S: 全曲数
- gumi: Gumiが歌う曲数
- ia: Iaが歌う曲数
- mayu: Mayuが歌う曲数
- Int: アルバムのパターン数
各曲に対して、各一名ずつ歌う場合(3パターン)、各二名ずつ歌う場合(3パターン)、三人全員が歌う場合(1パターン)の合計7パターンあります。なので7のS乗回試行して条件を満たすものをカウントすればよいのですが、Sが50の場合には1.798465e+42回ほど試行する事になるので残念ながら僕が死ぬまでには計算が終わらなそうです。
この手の問題はどうやら以下の二種類の方法で解けるようです。
- 場合分けをして数学的に解く
- 動的計画法で解く
前者は場合分けを行ってCombinationを駆使して解く方法、後者は分割統治法とメモ化と呼ばれる手法を使って問題を細分化して同じパターンの部分をキャッシュしながら解く方法です。勿論、数学的に解けた方がエレガントではあるのですが、Top Coderでは動的計画法は必須知識らしく、他の多くの問題に応用可能なようなので今回はこちらで解いてみました。
まずは各項が以下の漸化式で求められるという事に気づく必要があります。こちらは前述の通り各曲に対して7パターン存在するということからも分かると思います。
- f(s, g, i, m) = f(s-1, g-1, i, m) + f(s-1, g, i-1, m) + f(s-1, g, i, m-1) + f(s-1, g,-1 i-1, m) + f(s-1, g-1, i, m-1) + + f(s-1, g, i-1, m-1) + f(s-1, g-1, i-1, m-1)
- f(0,0,0,0) = 1
できあがりは以下のようなコードになりました。でも、やっぱこのレベルの問題を30分で完璧に解くのはまだまだ無理だなぁ。あ、ちなみに1000000007で割ってるのは問題文に数値がでかすぎるのでこの値の剰余をとるようにって書いてあったから。
import java.util.*;
public class VocaloidsAndSongs {
long cache[][][][];
final long MOD = 1000000007L;
public int count(int S, int gumi, int ia, int mayu) {
cache = new long[S + 1][gumi + 1][ia + 1][mayu + 1];
for (int s = 0; s <= S; s++) {
for (int g = 0; g <= gumi; g++) {
for (int i = 0; i <= ia; i++) {
for (int m = 0; m <= mayu; m++) {
cache[s][g][i][m] = -1L;
}
}
}
}
return (int) dp(S, gumi, ia, mayu);
}
private long dp(int s, int g, int i, int m) {
if (s > (g + i + m)) {
return 0;
}
if (s == 0) {
if (g == 0 && i == 0 && m == 0) {
return 1L;
} else {
return 0L;
}
}
if (g < 0 || i < 0 || m < 0) {
return 0L;
}
if (cache[s][g][i][m] == -1L) {
cache[s][g][i][m] = dp(s - 1, g - 1, i, m) +
dp(s - 1, g, i - 1, m) +
dp(s - 1, g, i, m - 1) +
dp(s - 1, g - 1, i - 1, m) +
dp(s - 1, g - 1, i, m - 1) +
dp(s - 1, g, i - 1, m - 1) +
dp(s - 1, g - 1, i - 1, m - 1);
}
return cache[s][g][i][m] % MOD;
}
}
2014年2月9日日曜日
Top Coder SRM 608 Level3 おさらい
問題は要約するとN個のノードからなる有効グラフが渡された時にステップ数Lからなる経路の数が多項式P(L)で表されるか判別するプログラムを書くというのが問題です。本番では英語だし若干複雑なので理解するのに若干時間がかかりましたが…。
入力値は個々のエッジを表すYとNの文字の羅列が以下のようにStringのArrayとして渡される。配列長と文字数はグラフの頂点の数と同じです。
String[] graph = new String[]{"NYN","NNY","YNN"};
また、出力は多項式解が存在する場合には"Bounded"、存在しない場合には"Unbounded"をリターンするだけです。
この問題は本番時にはコード以前にそもそもどういうアルゴリズムにすれば解けるのかが思いつきませんでした。終了後に以下のようにホワイトボードを使って精査したらやっとひらめいた。

NPがNon Polynomial(多項式解なし)でPがPolynomial(多項式解あり)を表しています。どうやら循環して自分に戻ってくるような経路を二つ以上もつノードがある場合に多項式解がなくなるようです。赤のラインで循環を示しているのですが、このラインが一つのノードから2つ以上出ている場合に多項式解がなくなります。例えば循環経路がM、自分に戻ってくるまでにNステップかかると経路数の計算は「Mの(L / N)乗」になるはずです。という訳でMが1の場合には多項式解、Mが2以上の時には多項式では解けないはず。
ルールさえ分かってしまえばコードはこんな感じで簡単に書けました。単純に一つ一つのノードをイテレートして循環が2つ以上ないか確認するだけです。
import java.util.*;
public class BigOEasy {
static final String UNBOUNDED = "Unbounded";
static final String BOUNDED = "Bounded";
boolean[][] edges;
public String isBounded(String[] graph) {
// edges as boolean 2d array
edges = new boolean[graph.length][graph.length];
for (int i = 0; i < graph.length; i++) {
for (int j = 0; j < graph[i].length(); j++) {
edges[i][j] = (graph[i].charAt(j) == 'Y');
}
}
// each vertex
for (int currentVertex = 0; currentVertex < edges.length; currentVertex++) {
int num_of_circle = 0;
// each edge
for (int nextVertex = 0; nextVertex < edges[currentVertex].length; nextVertex++) {
// check if circular
if (edges[currentVertex][nextVertex]) {
if(checkCircular(currentVertex, nextVertex, new boolean[edges.length])){
num_of_circle++;
}
}
// unbounded if more than one circulars
if(num_of_circle > 1){
return UNBOUNDED;
}
}
}
return BOUNDED;
}
private boolean checkCircular(int startVertex, int currentVertex, boolean visited[]) {
visited[currentVertex] = true;
for(int nextVertex = 0; nextVertex < edges.length; nextVertex++){
if(edges[currentVertex][nextVertex]){
if(startVertex == nextVertex){
return true;
}else if(visited[nextVertex]){
continue;
}else{
if(checkCircular(startVertex, nextVertex, visited)){
return true;
}
}
}
}
return false;
}
}
ただ、Level 1で10分、Level 2で20分程度は消費すると考えるとLevel 3に費やせる時間は30分程度しかありません。ちょっと本番でこのレベルの問題がでたらかなりラッキーじゃないと時間内に解ける気がしませんね。今のところは確実にLevel 1とLevel 2を片付けることを目標とするか。忘れかけたJavaをググりながら書いているので、この辺りのTipsが身に付けば早く解けるようになってもう少しスコアがあがるはず。
2014年1月27日月曜日
Pythonでデータ分析ごっこ事始めしてみる
データサイエンティストも積極採用中なのですが、応募者全員に以下のデータ解析タスクをGitHubから提出するという課題を課しています。
Cambridge Energy Data Lab: EnergyDataSimulationChallenge
既に15フォークされていて、質の良いPull Requestも多く来ていて嬉しい限りです。Cambridge大学の学生もどんどん応募してきてくれています。皆さんもお暇な時に是非 :)
これが採用に非常に有効で、まずランダムにCVを送りまくっている応募者や、最低限のスキルの身に付いていない応募者のフィルタリングが非常に効率的に行えます。基本的にはこのプログラミングタスクの提出をしていない応募者のCVは一切確認しません。また、どの言語が得意なのか、どんなライブラリの扱いに慣れているか、どのように考えて分析を進めているのかなどなど、やはりコードを見ると非常に効率よく応募者のスキルを知る事ができます。
とか偉そうな事を言っておいて、実は僕はWeb Applicationの開発に集中しないといけないという言い訳があり、自分ではデータ解析部分に殆ど触れておらずデータサイエンティストに任せっきりにしていました。しかしながら採用活動をバンバンしている手前、それじゃいかんなと反省して、週末にちょっと時間をみつけて自分でもPythonでデータ解析をしてみました。
環境設定
まずはCanopyをインストールしました。こちらはPythonでのデータ解析に利用されるライブラリ群(NumPy、SciPy、Matplotlib、pandasなどなど)に加えてIPythonが搭載された統合環境です。これをインストールするだけで必要なツールが一気に揃うので、Macを使っている方には非常にお薦めです。分析結果はIPython Notebookにまとめると便利です。Web上でInteractiveにコードの実行が出来、かつDescriptionなども加えられて自分の分析がNotebookとしてまとめられるので分析結果の公開が非常にやり易いです。
以下のように実行すると、Plotに必要なライブラリが読み込まれ、かつ結果のグラフ等の出力がHTMLに出力されて便利です。
ipython notebook --pylab inline
UIはこんな感じ。
チャレンジ
覚えないと行けない事は非常に多いのですが、とりあえずはpandasのDataFrameとしてデータを取り込んで、Matplotlibで可視化するという事を目標にして、Challenge 2 - Visualization of Energy Consumptionsに取り組みました。主にデータの可視化、時系列変換、クラスタリングを行うタスクです。初めて触るということもありやっぱデータの扱いに慣れておらず、半日近くかけてなんとか以下の処理だけ済ませました。
- pandasにデータ取り込み
- そのままPlot
- データのDiffをプロット
- 時系列変換してプロット
- データの分類(クラスタリング)をしてプロット
ちなみに、Gitに載せておくとIPython Notebook Viewerというサービスで公開できて便利です。僕の分析はこちらから見られます。とりあえず最低要件だけはなんとか済ませたというレベルなので、暇を見つけてちょっとかっこ良く分析するかな。特に単純に平均から標準偏差を足して引いてしてるだけの分類がダサいので。
2014年1月17日金曜日
HerokuからS3へアクセスするRakeを作ってみた
Rakeの設定
Rakeのタスクはrailsコマンドでlib/tasks以下に生成される。
$ rails generate task loader
create lib/tasks/loader.rake
とりあえずこんな感じで作って。
namespace :loader do
desc "Load Data Files"
task :test => :environment do
puts "test"
end
end
実行できる。
$ rake loader:test
test
RSpecもこんな感じで書けました。generatorはないっぽいけどspec/tasks以下とかに置けばよいのでは。
require 'spec_helper'
require 'rake'
MyApp::Application.load_tasks
describe 'Rake Test' do
it 'run test' do
Rake::Task['test'].invoke('arg')
end
end
S3へのアクセス
RubyからS3の利用はAmazonのドキュメント(AWS SDK for Ruby)を見ながら設定したら思いのほか簡単にできました。 S3のアクセス情報はHerokuのConfigに突っ込んで環境変数として使います(Configuration and Config Vars)。ローカルから走らせる場合には環境変数に設定するかRakeコマンドに引数として渡す事もできます。
$ heroku config:set S3_KEY=xxx S3_SECRET=yyy S3_BUCKET=zzz
Adding config vars and restarting app... done, v21
S3_BUCKET => zzz
S3_KEY => xxx
S3_SECRET => yyy
まぁ、以下のようにrailsのconfigに置いちゃっても良いみたいだけど。ちなみにこれは接続に失敗した時に表示されるAWSライブラリのエラーメッセージです。
= Ruby on Rails
In a Ruby on Rails application you may also specify your credentials in
the following ways:
* Via a config initializer script using any of the methods mentioned above
(e.g. RAILS_ROOT/config/initializers/aws-sdk.rb).
* Via a yaml configuration file located at RAILS_ROOT/config/aws.yml.
This file should be formated like the default RAILS_ROOT/config/database.yml
file.
Rubyからのアクセスには、まず以下のGemを追加します。
gem "aws-sdk", "~> 1.32.0"
そうすると上で設定した環境変数を引っ張って下記のように接続からBucketの取得までできます。
AWS.config(access_key_id: ENV['S3_KEY'],
secret_access_key: ENV['S3_SECRET'],
region: 'us-west-2')
BUCKET = AWS::S3.new.buckets[ENV['S3_BUCKET']]
すると以下のように、key名のprefixでS3上のオブジェクトを取得したりデータを読み込んだりできます。オブジェクトの詳細な扱いとかはAWS::S3のクラスドキュメントにまとまっています。
BUCKET.objects.with_prefix(directory).each do |obj|
puts obj.key
puts obj.read
end
スケジューラへの追加
スケジュール化されたタスクを走らせる方法としては定期的にRakeコマンドを実行するHeroku SchedulerとClockworkなどのGemを利用する方法があるらしい。Heroku Schedulerはone-off dynos上で実行されるBest Effortサービスらしいが、とりあえずこっちの方が簡単そうなのでこちらで実装してみました。 Heroku Schedulerのアドオンを追加すると以下のような感じで簡単にJobの登録ができます。
実行後に以下のようにログを確認できます。
$ heroku logs -p scheduler
2014-01-16T18:07:59.715840+00:00 heroku[scheduler.7222]: Starting process with command `bundle exec rake test`
2014-01-16T18:08:00.376906+00:00 heroku[scheduler.7222]: State changed from starting to up
2014-01-16T18:08:04.282904+00:00 app[scheduler.7222]: Loading Files for 20140116
2014-01-16T18:08:04.719251+00:00 app[scheduler.7222]:
2014-01-16T18:08:04.719251+00:00 app[scheduler.7222]: [AWS S3 200 0.431475 0 retries] list_objects(:bucket_name=>"zzz",:max_keys=>1000,:prefix=>"pre")
2014-01-16T18:08:05.958921+00:00 heroku[scheduler.7222]: Process exited with status 0
2014-01-16T18:08:05.980991+00:00 heroku[scheduler.7222]: State changed from up to complete
ところで、Herokuのログってdefaultだと1500行までしか保持してくれないんですね。アドオン導入しないとな。やっぱPapertrailでしょうか。
2013年12月10日火曜日
Rails多言語対応
2.0.0p247 :010 > I18n.l Time.now
=> "Tue, 03 Dec 2013 17:19:04 +0000"
2.0.0p247 :022 > I18n.t "hello"
=> "こんにちわ世界"
どのLocaleを利用するかはI18n.localeに格納されています。
2.0.0p247 :026 > I18n.locale
=> :jp
2.0.0p247 :027 > I18n.default_locale
=> :en
言語リソースはymlで用意する。config/locales/*.ymlというファイルを作るとRailsが自動的に読み込んでくれる。
en:
hello: "Hello world"
jp:
hello: "こんにちわ世界"
ちなみに階層化できるので、きれいにまとめましょう。
en:
greeting:
hi:
world: "Hi World"
ippei: "Hi Ippei"
.(ドット)でつなぎます。
2.0.0p247 :004 > I18n.t("greeting")
=> {:hi=>{:world=>"Hi World", :ippei=>"Hi Ippei"}}
2.0.0p247 :005 > I18n.t("greeting.hi.world")
=> "Hi World"
2.0.0p247 :006 > I18n.t("greeting.hi.ippei")
=> "Hi Ippei"
若干ハマったのが、なぜかjp.ymlという言語リソースファイルを追加したのに読んでくれていない。Railsがconfig/locales/から自動的にロードしてくれるのだが、残念ながらファイルを追加した時には動的に呼んでないらしい。ファイルに新しいKeyをアペンドした時は読んでくれるんだけど。たぶんこのパラメータが起動時に作られるのだと思われる。
2.0.0p247 :001 > I18n.load_path
=> ["/Users/ippei/RubymineProjects/eneberg/vendor/bundle/ruby/2.0.0/gems/activesupport-4.0.1/lib/active_support/locale/en.yml", "/Users/ippei/Rubymine.....
また、application.rbからdefault_localeの変更やload_pathの追加をすることもできる。少なくともrails4.0.1では以下のようなComment OutされたエントリーがあるのでComment Inして任意の言語またはディレクトリを追加するだけ。
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
問題はI18n.localeにどうやって任意の言語を入れてあげるか。つまりどうやって言語を判別するか。 大まかに以下の方法があると思います。組み合わせて使ったりもします。グリーはAccept-Languageだったはず。
- ドメインで識別
- jp.example.com
- example.jp
- Query Stringで渡す
- example.com?locale=jp
- Pathに追加する
- example.com/jp
- Accept-Languageを見る
- Accept-Language:en-US,en;q=0.8,ja;q=0.6
- GeoIP
- ユーザ毎に設定を持たせる
今回はお手軽にQuery StringとAccept-Languageで実装しました。
まずはQuery Stringから。ApplicationController.rbに下記を追加してQuery Stringで渡されたパラメーターをI18n.localeに設定するようにします。
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
これだけだと画面遷移時にlocaleが引き継がれないので、以下のmethodをoverrideして常にlocaleパラメータを渡すようにします。
def default_url_options(options={})
{ locale: I18n.locale }
end
お次はAccept-Languageの実装です。残念ながらRails自体にはAccept-LanguageをParseする機能はないようなので、http_accept_languageというGemを使いました。
Gemfileに以下を追加します。
gem "http_accept_language", "~> 2.0.0"
そうするとこんな感じで準備したLocaleに対応する言語を返してくれます。
http_accept_language.compatible_language_from(I18n.available_locales)
Query Stringを優先させるので、終わってみるとApplication Controllerはこんな感じになりました。
before_action :set_locale
def default_url_options(options={})
{:locale => I18n.locale}
end
def set_locale
I18n.locale = extract_locale_from_params ||
extract_locale_from_accept_language_header ||
I18n.default_locale
end
private
def extract_locale_from_params
if params[:locale] and I18n.available_locales.index(params[:locale].to_sym)
params[:locale]
end
end
def extract_locale_from_accept_language_header
http_accept_language.compatible_language_from(I18n.available_locales)
end
後はja.ymlとen.ymlにひたすらリソースを追加して、Templateにせこせこと以下の文字を馬鹿みたいに埋め込み続けるだけの簡単なお仕事です。
<%= t('KEY') %>
2013年12月1日日曜日
DNSimpleでHerokuアプリのドメイン登録
Herokuとの連携が簡単そうだったのでDNSimpleというドメインサービスを利用してみたら死ぬほど簡単だったので紹介してみる。DocumentもSimpleにまとまっていて良い(DNSimple Support)。
HeokuのドキュメントもDNSimple推しでまとまってます(SSL Endpoint, Purchasing an SSL Certificate from DNSimple)。
まずはクレジットカードの登録をしてアカウントアクティベートしてみます。ドメインを追加します。フォームに打ち込むだけで取得できるかの確認や、Name Servreへの登録とかもやってくれて数分待っていれば名前が解決できるようになりました。
既にとられているドメインだと怒られる。
こんな感じでダッシュボードから登録の状況やALIAS、SOA、NS等の情報が確認できます。
Advance Editorという画面からRecordが登録できるので、サブドメインと一緒にHerokuのアプリへのALIASレコードを作ってやります。ALIASレコードはDNSimpleが追加してたCNAMEの拡張レコードのようなもの。Aレコードがなくてもdomain名からアドレスを解決してくれるものらしい。詳しくはこちら(What is an ALIAS record?, Introducing the ALIAS Record – Naked Domain Aliasing that Works!)。
後は、Herokuのアプリ設定で上で追加したDomainを追加してあげればOK。ここまでで、もう作ったばかりのサブドメインでアプリに接続できるようになりました。
お次はSSLの設定。これもしっかりまとまっています(Using an SSL Certificate with Heroku)。まずはダッシュボードからこんな感じでサブドメインを指定して証明書を購入します。これも一瞬で済みます。サブドメイン一つのみだと$20/year、ワイルドカードだと$100/yearっぽいです。
購入すると発行期間からemailでkeyが送られてくるので、こんな感じで証明書とPrivate Keyを設定。
$ heroku certs:add /tmp/server.crt /tmp/server.key /tmp/bundle.pem
Resolving trust chain... done
Adding SSL Endpoint to .$oldapp.. done
$oldapp now served by $newapp
Certificate details:
Common Name(s):
Expires At:.....
注意点としては$newapp.herokussl.comっていうアプリ名がSSL用のエンドポイントとして割り振られるので、ALIASの先をherokuapp.comから変更すること。じゃないと、証明書のドメインと一致しなくて激おこされます。こちらに書いてある通りです(Troubleshooting SSL error for *.heroku.com or *. herokuapp.com)。もともと非SSLのアプリへのALIASにしてあったので、キャッシュの関係で変更後もしばらくは怒られていましたが一晩おいといたらちゃんとアップデートされてhttpsでアクセスできるようになりました。
後は以下のようにConfigでProduction環境のみhttpsを強制するようにすれば終了。
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -40,7 +40,7 @@Application.configure do
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
- # config.force_ssl = true
+ config.force_ssl = true
という感じで初めての僕でも作業時間半日くらいでドメインを取得してサブドメインでSSL対応のWebアプリを公開するとこまでできてしまいました。もう一度やったら1-2時間で済みそう。ちなみにBatch Server用のAWSのドメイン登録もしたんだけど、こちらはPublic IPが割り振られているのでAレコードを追加するのみでした。
2013年11月27日水曜日
EC2とS3の設定してみた
- EC2をSFTPサーバとして外部からファイルを受け取る
- EC2はファイルのバリデーションをしてS3と必要なデータをSync
- HerokuのアプリケーションがS3からデータ取得
Amazon S3
まずはBucketを作ります。
とりあえずRegionはHerokuに合わせてUSにしておく。
$heroku info
=== $server_name
Addons: heroku-postgresql:dev
Git URL: git@heroku.com:$server_name.git
Owner Email: test@example.com
Region: us
Repo Size: 2M
Slug Size: 36M
Stack: cedar
Tier: Legacy
Web URL: http://$server_name.herokuapp.com/
Amzon S3のConsoleから管理ができる。
Amazon EC2
次にFTP Server / Batch Serverとして使うEC2の設定です。これも基本的にはAmazonのチュートリアル(Getting Started with Amazon EC2 Linux Instances)通りに進めればすぐにインスタンスが立てられます。まずはOSを選ぶんですがAmazon Linux、Red Hat、SUSE、UbuntuからWindowsまで選択肢が多くて困る。Debianに慣れているしUbuntu AMIにしようかとも思ったけれども、無難にAmazon Linux AMIにした。とりあえず基本的なパッケージが安全に動けば良いし、AmazonのDocumentもAmazon Linuxを基準にしてあるみたいなので。
後はメモリやCPUやストレージサイズなどを適当に選んでいけばインスタンスが立ちます。最後にKey Pairが作れるのでそのPrivate Keyを使ってsshで接続すればすぐにLoginできます。
$ ssh -i ~/.ssh/amazon_ec2.pem ec2-user@pub_dns
Last login: Mon Nov 25 10:14:54 2013 from host
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
これもAmazon EC2のConsoleからInstance増やしたりVolume追加したりなどの管理ができます。
ついでにEBS Volumeの作成とマウントもしといた。VolumeはEC2のコンソールから作るだけ。初回のみはVolumeのフォーマットが必要なので注意。でないとマウントでエラーになります。とりあえずext4にしといた。
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 7.9G 1023M 6.8G 13% /
tmpfs 298M 0 298M 0% /dev/shm
$ sudo mkfs -t ext4 /dev/xvdf
mke2fs 1.42.3 (14-May-2012)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
327680 inodes, 1310720 blocks
65536 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=1342177280
40 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
$ sudo mkdir /mnt/ebs
$ sudo mount /dev/sdf /mnt/ebs
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 7.9G 1023M 6.8G 13% /
tmpfs 298M 0 298M 0% /dev/shm
/dev/xvdf 5.0G 138M 4.6G 3% /mnt/ebs
EC2からS3へのデータ転送
まずは例のごとくAmazonのドキュメントを見ながらCliの初期設定をします(Getting Set Up with the AWS Command Line Interface)。Access Keyの設定とかPythonライブラリのインストールとかあって若干めんどくさい。
Pythonで書かれてるらしいんだけど、Localeの設定をしてあげないと以下のように盛大に死ぬので注意。
$ aws
Traceback (most recent call last):
File "/usr/bin/aws", line 15, in
import awscli.clidriver
File "/usr/lib/python2.6/site-packages/awscli/clidriver.py", line 29, in
from awscli.help import ProviderHelpCommand
File "/usr/lib/python2.6/site-packages/awscli/help.py", line 20, in
from docutils.core import publish_string
File "/usr/lib/python2.6/site-packages/docutils/core.py", line 20, in
from docutils import frontend, io, utils, readers, writers
File "/usr/lib/python2.6/site-packages/docutils/frontend.py", line 41, in
import docutils.utils
File "/usr/lib/python2.6/site-packages/docutils/utils/__init__.py", line 20, in
import docutils.io
File "/usr/lib/python2.6/site-packages/docutils/io.py", line 18, in
from docutils.utils.error_reporting import locale_encoding, ErrorString, ErrorOutput
File "/usr/lib/python2.6/site-packages/docutils/utils/error_reporting.py", line 46, in
locale_encoding = locale.getlocale()[1] or locale.getdefaultlocale()[1]
File "/usr/lib64/python2.6/locale.py", line 478, in getdefaultlocale
return _parse_localename(localename)
File "/usr/lib64/python2.6/locale.py", line 410, in _parse_localename
raise ValueError, 'unknown locale: %s' % localename
ValueError: unknown locale: UTF-8
CredentialsのペアはSecurity Credentialの管理ページから作れる。aws configureでAccess Keyを設定すると~/.aws/configに設定ファイルが作られる。
$ aws configure
AWS Access Key ID [None]: $KEY_ID
AWS Secret Access Key [None]: $SECRET_KEY
Default region name [None]: us-west-2
Default output format [None]: json
やっとアクセスできるようになった。
aws s3 ls s3://arita_test
2013-11-19 17:22:58 300 2013-11-19-17-22-57-69ED20ABB5DBF2F7
2013-11-19 17:27:56 326 2013-11-19-17-27-55-8498FB7A97E32996
2013-11-19 17:31:41 299 2013-11-19-17-31-40-81265F67425272DE
2013-11-19 17:33:08 584 2013-11-19-17-33-07-87A40B3132B18A50
regionの指定で少しハマったけど、US StandardではなくEC2と同じRegionでS3のBucketを作り直したら上手く行った。aws configureで指定したregionと違う場合は--regionオプションで指定してあげないと上手く行かない。
$ aws s3 cp test s3://arita_test/ --region us-east-1
upload: ./test to s3://arita_test/test
$ aws s3 sync s3://arita_test/ s3
download: s3://arita_test/test to s3/test
SFTP用のユーザ作成
$ sudo adduser arita
$ sudo passwd arita
Changing password for user arita.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
公開鍵を置いてPerissionの設定。
$ su arita
Password:
$ mkdir .ssh
$ chmod 700 .ssh/
$ vim .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys
これでとりあえず、SFTPでデータを置いてS3にSyncするところまでは完成。
2013年10月19日土曜日
Facebook 広告を試してみる
まず、右上のアイコンから広告の作成ページに飛ぶ事ができます。
で、Headlineや説明や画像を設定したりできるのですが、ターゲティング機能が恐ろしくすごいです。
まずは市町村区単位での地域、年齢や性別の絞り込みは当然として、興味などでも絞り込みができます。例えば以下では東京都港区在住の30才以下でArsenalというサッカーチームに興味のある男女に絞り込んでいます。
ちなみに、絞り込みを調整しながら、ターゲットの数が何人くらいになるのか、広告のクリック単価がいくらになるのかというのも確認する事ができます。
後は、予算と期間を決めて広告を出すだけです。
実際に広告がはじまると以下の画面からPVやらクリック数やらの詳細情報が見られるようになります。また、広告のストップなどもすぐに行う事ができます。
ところで、広告が始まった瞬間に以下のような画面が現れて、広告のアカウントが止められてしまうという問題が発生しました。サポートに怒りのメールを投げてみたら2日ほどで対応して直してくれました。どうやらPay PalのBilling Addresと僕の現在地や広告先が違っていたのが原因だったようです。
2013年10月18日金曜日
Rails Operation in Heoku
基本的にはHeroku Toolbeltを利用してオペレーションをする事になり、簡単な運用方法はHeokuのサイトにまとまっています。
Getting Started with Rails 4.x on Heroku
けっこーな数のコマンドがあります。
$ heroku help
Usage: heroku COMMAND [--app APP] [command-specific-options]
Primary help topics, type "heroku help TOPIC" for more details:
addons # manage addon resources
apps # manage apps (create, destroy)
auth # authentication (login, logout)
config # manage app config vars
domains # manage custom domains
logs # display logs for an app
ps # manage dynos (dynos, workers)
releases # manage app releases
run # run one-off commands (console, rake)
sharing # manage collaborators on an app
Additional topics:
account # manage heroku account options
certs # manage ssl endpoints for an app
drains # display syslog drains for an app
fork # clone an existing app
git # manage git for apps
help # list commands and display help
keys # manage authentication keys
labs # manage optional features
maintenance # manage maintenance mode for an app
pg # manage heroku-postgresql databases
pgbackups # manage backups of heroku postgresql databases
plugins # manage plugins to the heroku gem
regions # list available regions
stack # manage the stack for an app
status # check status of heroku platform
update # update the heroku client
version # display version
Dynoのステータスの確認
heroku ps
=== web (1X): `bin/rails server -p $PORT -e $RAILS_ENV`
web.1: up 2013/10/17 17:38:06 (~ 1h ago)
Rails Consoleもリモートの環境のものがこんな感じで使えてしまいます。
$ heroku run rails console
Running `rails console` attached to terminal... up, run.2213
Loading production environment (Rails 4.0.0)
irb(main):001:0> User.all
=> #<ActiveRecord::Relation [#<User id: 2, email: ...
rakeのCommandもheroku runとタイプするだけで走ってしまう。例えばdb:migrateだったらこんな感じ。
$ heroku run rake db:migrate
Running `rake db:migrate` attached to terminal... up, run.6382
Migrating to DeviseCreateUsers (20131014182214)
== DeviseCreateUsers: migrating ==============================================
-- create_table(:users)
-> 0.0243s
-- add_index(:users, :email, {:unique=>true})
-> 0.0076s
-- add_index(:users, :reset_password_token, {:unique=>true})
-> 0.0087s
== DeviseCreateUsers: migrated (0.0419s) =====================================
$ heroku run rake db:seed
Running `rake db:seed` attached to terminal... up, run.6750
ただ、rake db:migrate:resetとかのDBを書き換えちゃうようなコマンドはPermissionで怒られます。
$ heroku run rake db:migrate:reset
Running `rake db:migrate:reset` attached to terminal... up, run.2597
FATAL: permission denied for database "postgres"
DETAIL: User does not have CONNECT privilege.
そんな時はheroku pgコマンドで対応できるっぽい。
$ heroku pg:reset DATABASE
! WARNING: Destructive Action
! This command will affect the app: $host
! To proceed, type "$host" or re-run this command with --confirm $host
> $host
Resetting HEROKU_POSTGRESQL_AMBER_URL (DATABASE_URL)... done
うーん。超簡単ですね。今後はDatabase周りの細かいオペレーションが必要になってくると思うので、この辺をみながらいじってみて勉強しとこっと。
2013年10月10日木曜日
RSpec with Rails4
導入は相変わらず超簡単でGemfileにこんな感じで追加してbundle installした後にrails genearateで必要なファイルを生成するだけ。
# RSpec group :development, :test do gem 'rspec-rails', '~> 2.0' end
bundle install rails generate rspec:install
モデルを作ると以下のようにTest:Unitの代わりにSpecを自動生成してくれる。
rails generate model test name:string
invoke active_record
create db/migrate/20131011100432_create_tests.rb
create app/models/test.rb
invoke rspec
create spec/models/test_spec.rb
Specだけ作りたい時はこんな感じ。
rails generate rspec:model user
create spec/models/user_spec.rb
describe User do
before :each do
@testee = User.create! email:'hoge@hoge.com', password:'testtest'
end
it 'has fields' do
expect(@testee.email).to eq('hoge@hoge.com')
expect(@testee.password).to eq('testtest')
end
end
bundle exec rspecで実行はできますが、.rpecファイルか引数でformat指定するとSpecの出力もしてくれて少し幸せになれる。
bundle exec rspec --format documentation User has fields Finished in 0.40579 seconds 1 examples, 0 failures Randomized with seed 13270
という感じで安定のお手軽さに感動しました。
2013年10月9日水曜日
Railsでモデル生成のお勉強中
とりあえずrake generate modelでモデルの定義をするとmodel classとそのUnit Testとdbのmigration fileをわんさか作ってくれます。DBのmigration手順はここ(Rails Guide - Active Record Migrations)に良くまとまっていますが、必要に応じてindexやrelationなんかを追加しつつrake commandで簡単にDBを作る事ができます。rake db:migrateでdb/migrate以下に作られたmigration fileを元にじゃんじゃかテーブルを作ります。以下の順序で行われるっぽい。
- db/migrate以下のファイルからテーブルを作成
- データベースからdb/schema.rbを作る
少しハマった…。
rakeのコマンドとかもまだ全く覚えていないのですが、rake --tasksで他のタスクがぞろぞろでてきてくれます。rake -Pで親タスクやその依存関係とかも出力してくれるっぽい。
例えば上記のdb:migrate:resetは3つのタスクを組み合わせたものらしい。
rake db:migrate:reset
db:drop
db:create
db:migrate
また、rake test:allでUnit Testの全実行をしてくれるっぽい。db/seed.rbに開発環境用のデータを用意できる。rake consoleから実行するのと同じように$class.new(:$field1 => $value)みたいな感じで書ける。RubyのScriptなのでファイルから読み込んでLoopでオブジェクト生成とかも非常に簡単にできそう。rake db:seedだと単純にseed.rbからデータをLoadする。rake db:setupだとスキーマごと作り直してからデータをLoadする。ちょこちょこデータファイルを変更する時は後者を使う。
あ、後作ったModelやそのObjectはrails consoleから確認してったら超効率よくできた。こんな感じで一通りモデルを作って、DBに反映させて、テストして、開発用データの準備までが半日かからずにできちゃいました。DBとModelの定義を固定して厳しい命名規則を受け入れるだけでこれだけの恩恵をうけられるとは。明日はRSpecを導入する予定。Rails楽しいね。
2013年10月8日火曜日
Cambridge到着
ケンブリッジで落ち着くまでの一ヶ月間は本当にドタバタでした。転職直後で慣れない仕事を進める傍ら、大学で授業を行いつつ、もろもろの住所変更やら部屋の引き払い等の引っ越し準備を行い、数多くの送別会でお別れを言いつつ、さらに父親が心筋梗塞で倒れるという災難まで重なり毎週名古屋に帰省するという、間違いなく僕の人生で一番大変だった訳の分からない一ヶ月間でした。幸い一度は心臓が止まった父親は後遺症もなく順調に回復し、僕も無事予定通りにケンブリッジに辿り着く事ができました。と思いきや初日というか飛行機の中から体調を崩して到着日に救急病院のお世話になるという超ドタバタが続き、体力的にも精神的にも疲弊しきっている状態だったのですが、仲間の支えもあり一週間たった今では十分に落ち着いて仕事に集中する環境ができています。
初めの週で銀行口座開設、携帯電話の契約、NHS(国民保険サービス)の登録、職場での環境設定、自転車購入などの必要最低限の生活インフラもひと通り整い、町にも少しずつ慣れてきました(まだけっこー迷うけど)。同じようなスタートアップ企業が集まるCo-Workingスペースが職場なのですが、早速他の会社の日本企業との商談を手伝ってあげたりして人間関係も非常に上手くいっています。
食べ物も思っていたよりは遥かにまともそうです。レストランもちょっと値段は高いけど十分美味しいし、スーパーも豊富にあるので近くのコリアンショップで肉を買って焼き肉をしたり、チキンを一匹オーブンで焼いて食べてみたり、日本のカレーライスを作ってみたりなどなどして食事を楽しんでいます。また、こちらは食べ物のデリバリーがすごく盛んなのでJUSTEATで調べれば数えきれないくらい多くデリバリー料理が見つかります。
父親の件もあり自分のこれからの人生や生死なんかについて一度落ち着いて考えてみたいななんて思ったりもする訳ですが、とりあえずは後悔のないように新しい仕事に全力で打ち込んでみたいと思います。街を案内できるくらいにはなっておくのでイギリスにお越しの際には是非お立ち寄りください。
2013年9月20日金曜日
Ruby2.0.0 & rails4 & Postgres on Herokuの環境づくり
Ruby Mine
IntelliJに慣れつつある僕はRubyMineを使いたい。VimのKeybinding使えるし、デバッグしやすいし、安定しているし、良い!
Ruby on Rails
Homebrewとgemで適当にインストールした。超簡単なので覚え書きもしません。
RVM
その後、RVMでバージョン使い分けようとしたら少しはまった。たぶんHomebrewのと干渉したんだと思う。
https://rvm.io/
こんなエラーが出てしまった。
/Users/ippei/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/mkmf.rb:434:in `try_do': The compiler failed to generate an executable file. (RuntimeError) You have to install development tools first.
以下をしてruby2.0.0とsqlite3をインストールし直したら直った。
rvm get head rvm --force install 2.0.0 gem install bundle gem install sqlite3
Postgres
Postgresはここを見ながら設定。Macでの設定はPostgres.appを使うと一瞬で済む。
https://devcenter.heroku.com/articles/heroku-postgresql
と思いきや何故かSocketのI/Oの場所がpgライブラリが見に行く場所と違ってエラーになるっぽいので、無理矢理以下のlinkを作って解決。
lrwxr-xr-x 1 root wheel 4 Sep 10 09:14 /var/pgsql_socket -> /tmp
後はPostgresにアプリケーション名でユーザを作りつつ。
$ createuser -U ippei -P $user_name Enter password for new role: Enter it again: Shall the new role be a superuser? (y/n) n Shall the new role be allowed to create databases? (y/n) y Shall the new role be allowed to create more new roles? (y/n) nrakeでDBを作る。
#rake db:create
Heroku
とりあえず、Herokuのインストラクションをみながら設定。すでにsqliteでひな形を作ってしまっていたので少しつまづいた。Herokuは基本Postgresぽいです。
以下のツールベルトというのがコマンドラインツール。いろいろ便利。
https://toolbelt.heroku.com/
Reference
https://devcenter.heroku.com/articles/rails4-getting-started
https://devcenter.heroku.com/articles/heroku-postgresql
2013年9月16日月曜日
非常勤講師@早稲田大学 - モバイルプログラミング
でも授業の出来としては上々で、生徒全員が毎日出席してくれましたし、プログラミングの経験が乏しかった生徒達も最後の課題ではjQueryとTwitter Bootstrapを使ってレスポンシブなUIを作ったり、Google Chartsでグラフを作って利までできるようになりました。やはり皆さん若くて覚えが早いからかw、僕の期待よりは遥かに早いスピートで吸収してくれました。
今回のクラスでは「ドットインストール」をかなり活用しました。動画で学べる初心者向けのプログラミングサイトです。ドットインストールの動画を見せて、僕がライブコーディングをしてみて、生徒に実際に試してもらうというステップで進めてみました。やっぱり僕が空いた時間でちょこちょこ作った雑な資料なんかを使うより、より質の高い資料を生徒に会わせて上手く作った方が上手く教えられるという事が実感できました。これまでは教科書を使って授業という形が主でしたが、今後は授業によっては「Coursera」とかの外部の質の高い講義ごと利用しちゃったりした方が質の高い教育ができるんじゃないかななんて思ったりしました。そうすれば講師が個々の生徒のフォローに使える時間も増えそうですしね。
前回と同じように授業で使ったスライドとコードはSlideShareとGitHubで公開しています。また資料や生徒の課題はWebで公開してあります。
GitHub: https://github.com/peisan/WasedaMobileProgrammingClass
URL: http://mpwaseda.herokuapp.com/
2013年9月7日土曜日
非常勤講師@早稲田大学 - Java Programing上級
大学の先生達と同じ事をしていては面白くないので、IntelliJ、Github、Homebrewなどを導入して実際に僕がグリーで行っていた開発環境に近いような形で授業を進めてきました。最後の課題では素因数分解のプログラムを書いて貰ったりしたのですが、終了時にはPull Requestで提出してもらいました。
開発環境のセットアップに思った以上に時間がかかったりなど反省すべき点も多々ありましたが、生徒も楽しんで積極的に授業に参加してくれましたし、何よりどんどん吸収して上達していく生徒を見ているのが僕も楽しかったです。
ちなみに授業で使ったプログラムはgithubで公開、スライドはSlide Shareで公開しています。
github - https://github.com/peisan/WasedaAdvancedJavaClass
2013年9月5日木曜日
グリーで覚えた&忘れた単語リスト
覚えた
- CDN
- LVS
- Web Storage
- App Cache
- CSRF
- SPOF
- UX
- DAU
- MAU
- UU
- ささる
- くばる
- デグレる
- 上長
- リア充
- ネト充
- スイーツ()
- ボトラー
- 懐古虫
- イカ娘
- ノ
- まどマギ
- プギャー
- モヒカン
- マサカリ
- ラブライブ
- Homebrew
- git-flow
- Coffee Script
- Tyepe Script
- Zepto
- node.js
- PHP
- Ethna
- Shading
- Master / Slave
- play framework
- finagle
- sbt
- Redis
- DDD
- Monad
- Scrum
忘れそう
- Bloomberg Tickers (jb/js/jl/...)
- Reconciliation
- Tweak
- PNL
- Delta
- FUTEQ
- PVBP
- Interpolation
- fix / float leg
- xccy
- basis swap (e.g. 3m / 6m)
- fixing risk
- LIBOR / TIBOR / EURIBOR
- Spring Framework
- RMI
- RMDS
- dbunit
2013年8月25日日曜日
卒グリー(中退かも)
思い起こせば入社時には、
入社当時は、大手の証券会社という全く別の業界からきた事もあり、コミュニケーション面でも、技術面でも勝手が分からずおどおどしていたのを覚えています。「IRC?LVS?CDN?DAU?SPOF?なんだそれ?」みたいな。システムのリリース時にも何百台という単位のサーバにデプロイをするのはWeb業界のない僕には初めての経験で、初めは心臓バクバクでした。大きなミスをやらかしたりもしました。そんな僕でしたが数百万DAUという巨大Webサービスが如何にして運用させているのかというノウハウも少しずつ身につけ(実はけっこー日曜大工的ですw)、後半には海外のチームとの共同プロジェクトのマネジメントや、新規プロダクトの立ち上げ業務や、非常に技術力の高いエンジニア達のマネジメントも任せてもらえるようにまでなりました。特にかとじゅんや上村君の元ドワンゴ勢と一緒に仕事するのは本当に刺激的でした。本当はかとじゅんからもっと色々吸収したかったな。
グリーに入って一番感じた事は、技術好き、プロダクト好きの人の多さと、現場の裁量の大きさでした。やはりJPMorganという巨大な国際的大企業から、グリーという大きくなったとはいえまだベンチャー気質の残るインターネット企業への転職ですから、インパクトが大きかったのだと思います。
本当に技術が好きで、自分の作っているプロダクトが好きで、それが世に出てサービスとして使ってもらえる事を一番の喜びにしている人たちが本当に多かったです。プロダクトとかじゃなくて、常に自分の好きな技術を押し通してみたいな人達もいたしw。JPMorganにいた時は、モチベーションは「お金を稼ぐ」という人が殆どだったと思いますが、グリーは本当に多様で、モチベーションって人によってこんなに違うんだなというのを強く感じました。
裁量の面では、グリーでは与えられた仕事の枠をいくらでも広げたり壊したりできるというか、そもそも枠自体がすごく曖昧。
あと、CTOの藤本さんにも驚かされました。CTOなのに現場レベルの仕事に自ら積極的に関わってくれている。僕も一度ヘマをした時に、付きっきりでフォローをして頂いた事がありました。マネジメントも現場のエンジニアを理解して、いかに僕らが仕事をしやすくするかを考えて進めてくれていました。憧れの存在です。
あ、なんかこう比べるとJPMorgan批判みたいになってしまいましたが(汗)、前職で身につけた能力があったおかげでグリーでもこれだけの事を吸収できたのだと思います。日本国内のエンジニア職であれだけグローバルな環境で働けたというのは本当にありがたい経験でした。国際感覚はかなり身につきましたし、証券業務のという複雑で専門性の高い知識、もちろんシステム開発や運用のスキルも身につきました。おかげで転職時も引く手数多でしたし:)
そうそう、最後に、グリーで働いたせいで「リア充」という言葉もしらないくらいリア充だった僕が、たった1年ちょっとでかなりWeb系のヲタの人達に順応してきてしまいました。朝会社こないし、短パンにサンダルだし、変な言葉いっぱい覚えたし、実は最近では変なアニメとかも見るようにまで…。グリーを突き抜けてドワンゴ化してしまいました。
それでは次のチャレンジへと進んでいきたいと思います。グリーでお世話になった方々、壮行会で暖かく追い出してくれた方々、どうも有り難うございました。おかげさまでいつも笑顔で楽しく働く事ができました。
2012年4月30日月曜日
JPMorganからグリーへ
まず、JPモルガン証券を退職した理由ですが、従業員のレベルは本当に高く世界中からとびっきり優秀な人達が集まった素晴らしい職場でした。僕は債券システム部という部署にいたのですが、東京オフィスでさえチームメンバーのほとんどが外国人で、毎日のように世界中(ニューヨーク、ロンドン、シンガポール、香港、ムンバイなど)のメンバーと協力して業務を進めていたので国際感覚はかなり身につきましたし、証券業務のという複雑で専門性の高い知識を身に付けることもできました。勿論、システム開発や運用のスキルも身につきました。
ただ、証券会社ということもありエンジニアが主役ではない点や、大手金融機関ということでコンプライアンスが厳しく社内の手続きが猥雑という点はありました。なので、ここ数年間でFacebookやTwitterを始めとする世界を変えるほどのインパクを持つ新しいWebサービスがどんどん出てきて、Facebookの「The Hacker Way」に象徴されるようなエンジニアが先頭に立って自由にサービスを作り上げていくインターネット業界には強く憧れていました。
数あるインターネット企業の中からグリーを選んだ理由は、SNSに対する興味、エンジニアを重視するカルチャー、積極的な海外展開の三点です。
まず、SNSに対する興味ですが、僕はFacebookのヘビーユーザです。最近はSNSを利用することによって自分のコニュニケーションのスタイルが変わり、時間や場所を越えて効率的にコミュニケーションがとれるようになりました。最近では友達と連絡を取るときにはメールではなくFacebookメッセンジャーで話すことが多いですし、人と知り合うときにも携帯番号などではなくFacebookで友達申請し合うようになっています。グリーのSNSはまだFacebookほど洗練されたものではないかもしれませんが、ゲームとの連携や半匿名性のような特徴を利用してFacebookとはまた違うタイプの面白いプラットフォームになる可能性があると思ってます。
次にエンジニアを重視するカルチャーです。転職にあたって他社ともお話をしたのですが、私が検討した会社の中ではグリーが一番エンジニア主導の会社だというイメージを持ちました。社長が自ら作って始めたSNSサービスが会社の始まりですし、創業時のキープレーヤーの多くがエンジニア出身という点が大きく影響しているからだと思います。会社によってはエンジニアは他の人のアイデアを実現するためのリソースとしての位置づけという印象をもった所もありましたので、そこは大きな魅力でした。
最後に、積極的な海外展開ですが、グリーは世界市場をを狙える日本企業という点でもとても魅力的でした。今までは「世界展開している外資系大企業の東京支社」で働いていたので、意思決定権をもっているマネージャーがロンドンにいたりして、予算や技術的な枠組みがすべて海の向こうで決まった後に僕らがそれに合わせてプロジェクトにアサインされれローカライズするような形でした。なので、程よい規模で世界展開をすべく急激に成長している企業で働けるという点は大きな魅力でした。JPモルガンで海外のエンジニアチームと協力してプロジェクトを進める能力はかなり身についたと思うので、今度は日本から世界へという部分でその能力を活かせたら嬉しいです。
そんな感じで4月頭に入社して丁度一ヶ月経ちますが、基本的にはイメージしていた通りの会社で順調にやってます。特に、前職がマネジメントが強い会社だったこともあってか現場主導の環境にとても心地よさを感じていますし、カルチャーの違い(全然違うよ!)なども楽しめています。その辺りを含めて、まだブログに書きたい事はいくつかありますが、今回はこの辺で。
2012年4月22日日曜日
Graph APIとGAEでお遊びアプリ
http://pei-fbstats.appspot.com/
基本的にはfacebookのGraph APIを使って友達の性別や所属、コメントやLikeの数などを集計しているだけのアプリです。遥か昔に忘れたHTMLの書き方とか、GAEの使い方や初めて書くPythonやjQueryやKVS(結局使わなかったけど)の使い方とかを覚えながら、のべ二週間くらいかけて作りました。Feedのコメント数とかが微妙に上手く取れていないことがあるような気もしたりするので、お遊びの参考程度だと思っててきとーに使ってください。ユニットテストすら書いていないので…。気が向いたらちゃんと確認します。
なんか問題があっても責任はとりませんがw、当初のKVSのお勉強をするという目標とは裏腹に、実はデータは全くKVSにストアしていないのでデータ集めてるとかはないです(KVSは使ってみたし勉強はちゃんとしたけどね!)。でも、毎回Graph API叩くのはさすがにパフォーマンス的にどうかと思うので、cache目的で使った方がいいだろうなぁとは思ってます。まぁでもその目的ならBigtableではなくmemcachedになるか…。でも、たぶん転職直後で忙しくて触ってる暇はもうないですが。
以下、使ってるサービスとかライブラリの説明です。たぶんWebプログラミングに慣れてるひとからするとアホみたいな話でしょうが。僕が5-6年前に大学でやっていた頃と比べると、特にクラウドサービスとかJavascriptのライブラリの充実ぶりが半端無くて、本当に簡単にWebサービスが作れる時代になったんだなぁと実感しました。
GAE
サーバ借りたりとか面倒だし、勝手にスケールしてくれるし(そんなに使う人いないと思うけど)、僕みたいな怠惰な人間には最高のプラットフォームです。余談ですが、GAEではurllib2.urlopenは使えなくてgoogleの用意したurlfetchっていうライブラリを使わないといけないみたいです。socketが使えないのが理由みたい。軽くハマりました。詳しくはここで(The URL Fetch Python API)。
Facebook Graph API
言わずと知れたfacebookのAPIです。リクエストの数が多い時には複数のリクエストをまとめてPOSTできるbatch機能とかもあったりして便利でした。けっこー、レスポンスに時間がかかったりするのでtimeoutとかpagingとかのパラメーターを上手く調整する必要があります。でかいデータにアクセスしようとすると、時間かかったりレスポンスがなかったりするのはこいつのせいです。(嘘です。ぼくが怠惰でエラーハンドリングとかcacheとかしてないせいです。)
jQuery
Webに慣れてる人は何を今更って感じでしょうが、奇跡のライブラリですねこれは。恥ずかしながら今回はじめて使ったのですが、非同期の処理が本当に簡単にできてしまってjavascriptの敷居を一気に下げるツールです。6-7年前に自分でオブジェクト作ってブラウザごとに分岐したりしてAjaxの処理を作っていたのが懐かしい(というか馬鹿みたい)。
simplejson
Graph APIはJSONでデータを返してきますし、このアプリも基本的にサーバ側はJSONでデータを返すだけで、クライアント側がサーバから返ってきたデータを可視化しています。実はJSON形式のデータって今まで使ったことなかったんですが(証券会社勤務だったのでJavaでXMLみたいな堅いメッセージングばっかり)、すごくシンプルなデータ構造ですし、このライブラリを使ったら超簡単に扱えました。pythonの配列や辞書形式のデータとJSONの文法がほとんど同じだったなのですぐに慣れました。python2.6以降ではデフォルトで含まれているみたいですが、GAEがサポートしているpython2.5に含まれていないので自分で落としてきました。このチュートリアルが分かり易かった。
gae-sessions
後はwebappというGAEビルトインのフレームワークにはSession管理機能が含まれていないためgae-sessionsというセッション管理ライブラリを利用しました。たしかmemcachedを使ってるライブラリだったような。
Google Graph Tools
グラフはGoogleのAPIを利用しました。javascriptのオブジェクトにデータ突っ込むと勝手に綺麗なグラフを作ってくれます。pie chartとbar chartしか使わなかったけど本当はもっと色々と細かいことできるみたいです。
Graph API Explore
Graph APIで遊ぶなら必須ツールです。APIがどんなメッセージを返してくるのか簡単にチェックすることができます。
Favicon Generator
faviconはこれでテキトーに作りました。
git
Dropboxをレポジトリにしてgitで管理しました。一度、リファクタリングしたらGitHubに乗せてみようかな。
今後追加してもいいかなぁと思っているもの
- キャッシュ。毎回時間かかり過ぎだから。
- 人の名前をクにその人のFBページのリンクをつける。(Google Chart Toolsで簡単にできそう)
- 自分と一緒にタグ付けされている人のランキング
- 友達やグループメンバーのフィルタリングツール(友達を所属とか年齢や性別みたいな属性で絞り込むような機能。絞り込み後にメッセージ一斉送信とかできたら更に使えるかなみたいな。)



















