VOYAGE GROUP エンジニアブログ

voyagegroup_techのブログ
VOYAGE GROUPエンジニアブログです。

2014年08月

これは知らなかった!「エクセルでセル内にグラフを書く方法」に感動

JENGAでグラフ

こんにちは、VOYAGE GROUPの水越(@Akiyah)です。

エクセルを使っていると日常茶飯事に行われるグラフ作成

データの入ったセルをドラッグして、メニューからグラフを作成していると思います。

実はこのグラフ作成、多くの人が知らない便利な方法があると技術力評価会(※)で話題になりました。


スポンサードリンク



なんとグラフはセルの中に書けるのです!

1. まずグラフにしたい範囲を「ドラッグ」
2. そして「条件付き書式」から「データバー」



これだけですぐには理解できなかったセル内の数字の大小関係が直感的に理解できるようになります!
普通にグラフを書くよりも表示がコンパクトでいいですね。これぞVisualization。さすがExcelです。

このテクニックは株式会社adingoの@nakano_tomofumi技術力評価会(※)に参加したときに教えてもらいました。
データの可視化は意外と重要なので、身近なツールを使って手軽に出来るととっても便利ですね。

ぜひお試しあれ。


※技術力評価会とは
株式会社VOYAGE GROUPで半年に一回行われる、技術者の能力を技術者が評価する仕組み。
今回のように今まで知らなかったテクニックを知る事の出来るうれしい機会でもあります。
http://voyagegroup.com/design-and-tech/field/assessment/ 

iOS 8 で導入される選択肢付きの Push 通知を試してみた

こんにちは。VOYAGE GROUP で主に iOS アプリの開発をしている Swift はまだ様子見の @qmihara です。

iOS 8 では Push 通知に選択肢を付けられるようになりますね。
実際にどのようにすれば良いのか気になったので試してみました。

tech_blog-push_001
 
尚、本記事に記載されている内容は一般公開されているものをもとに記述しております。
画像につきましても一般公開されているものを引用しております。

環境

  • Xcode 6 beta 6
  • iOS 8 beta 5
  • Parse
お手軽に Push 通知を行うため Parse を使用しました。
便利です。

Push 通知の設定

(Push 通知の証明書の発行は従来と変わりありませんのでここでは省略します。)

iOS 8 から Push 通知の利用許可を求める方法が変わりました。
これまで `- registerForRemoteNotificationTypes:` でデバイストークンの取得、利用許可を求めるアラートの表示が行われていましたが、iOS 8 からはそれぞれ異なるメソッドを呼び出す必要があります。
[[UIApplication sharedApplication] registerForRemoteNotifications]; // <- Push 通知の利用登録(デバイストークンの発行)

UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings]; // <- 利用許可を求めるアラートの表示
`- registerForRemoteNotifications` の結果は、従来と同様成功時は `- application:didRegisterForRemoteNotificationsWithDeviceToken:` が、失敗時は `- application:didFailToRegisterForRemoteNotificationsWithError:` が呼ばれます。

`- registerUserNotificationSettings:` の結果は新たに `- application:didRegisterUserNotificationSettings:` メソッドが呼ばれます。
引数の `notificationSettings` に実際にユーザーが許可した内容が反映されています(Alert のみ、等)。

選択肢の設定

選択肢の設定は Push 通知の利用許可を求める際に併せて行います。
選択肢はアクションという単位で作成することになり、複数のアクションは一つのカテゴリに属することになります。
カテゴリは複数定義することが可能で、Push 通知を送る際に定義済みのカテゴリを指定することになります。

以下はカテゴリ、アクションの作成例となります。
UIMutableUserNotificationAction *acceptAction = [UIMutableUserNotificationAction new];
acceptAction.identifier = @"ACCEPT_IDENTIFIER";
acceptAction.title = @"Accept";
acceptAction.activationMode = UIUserNotificationActivationModeBackground;
acceptAction.destructive = NO;
acceptAction.authenticationRequired = NO;

UIMutableUserNotificationAction *maybeAction = [UIMutableUserNotificationAction new];
maybeAction.identifier = @"MAYBE_IDENTIFIER";
maybeAction.title = @"Maybe";
maybeAction.activationMode = UIUserNotificationActivationModeBackground;
maybeAction.destructive = NO;
maybeAction.authenticationRequired = NO;

UIMutableUserNotificationAction *declineAction = [UIMutableUserNotificationAction new];
declineAction.identifier = @"DECLINE_IDENTIFIER";
declineAction.title = @"Decline";
declineAction.activationMode = UIUserNotificationActivationModeBackground;
declineAction.destructive = YES;
declineAction.authenticationRequired = NO;

UIMutableUserNotificationCategory *inviteCategory = [UIMutableUserNotificationCategory new];
inviteCategory.identifier = @"INVITE_CATEGORY";
[inviteCategory setActions:@[acceptAction, maybeAction, declineAction] forContext:UIUserNotificationActionContextDefault];
[inviteCategory setActions:@[acceptAction, declineAction] forContext:UIUserNotificationActionContextMinimal];

NSSet *categories = [NSSet setWithObjects:inviteCategory, nil];
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:categories];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
 カテゴリは `UIMutableUserNotificationCategory`、アクションは `UIMutableUserNotificationAction` クラスを使用します。
アクションは識別子やタイトルなど必要な情報を設定します。

  • identifier
    • アクションを表す識別子
  • title
    • バナーやアラートに表示されるボタンタイトル
  • activationMode
    • Background、または Foreground を指定
    • Background であればアプリが起動することなく処理され、Foreground であればアプリが起動されます
  • destructive
    • ボタンタイトルを強調するかどうか
    • 削除など取り返しのつかない処理などで YES にする
  • authenticationRequired
    • YES を指定すると選択時にパスコードをの入力を求める
    • (iOS 8 beta 5 の時点では YES/NO に関わらず動きの違いはありませんでした。)
カテゴリには定義したアクションを設定するのですが、コンテキスト別でアクションを出し分けることができます。
コンテキストには以下の 2 種類があります。
  • UIUserNotificationActionContextDefault
    • ダイアログ表示時
    • 表示可能なアクションは最大 4 個
  • UIUserNotificationActionContextMinimal
    • バナー表示時
    • 表示可能なアクションは最大 2 個

選択肢付き Push 通知を送る

選択肢付きの Push 通知はペイロードに定義済みのカテゴリを指定することで送信することができます。
以下はカテゴリを指定したときのペイロード例です。
{
  "aps": {
    "alert": "Invitation from Jane Appleseed",
    "category": "INVITE_CATEGORY"
  }
}
tech_blog-push_002

tech_blog-push_003

次にアプリ側での通知の受け取り方です。
通知の選択肢がタップされた場合、`- application:handleActionWithIdentifier:forRemoteNotification:completionHandler:` メソッドが呼び出されます。
メソッドには定義したアクションの識別子が渡されますので、識別子に応じた処理を行うことになると思います。
最後に `completionHandler` を呼び出すのをお忘れなく。
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {
    if ([identifier isEqualToString:@"ACCEPT_IDENTIFIER"]) {
        // ...
    } else if ([identifier isEqualToString:@"MAYBE_IDENTIFIER"]) {
        // ...
    }


    if (completionHandler) {
        completionHandler();
    }

}
選択肢ではなくバナー自体やダイアログの開くをタップした場合は、iOS 7 から追加された `- application:didReceiveRemoteNotification:fetchCompletionHandler:` が呼び出されます。
これまでの `- application:didReceiveRemoteNotification:` は呼ばれなくなっているのでご注意ください。

おまけ

選択肢付きの通知は Local Notification でも利用できます。

送り方は `UILocalNotification` に `category` プロパティが追加されていますので、ここにカテゴリの識別子をセットします。
UILocalNotification *localNotification = [UILocalNotification new];
localNotification.alertBody = @"Local notification";
localNotification.category = @"INVITE_CATEGORY";
[application scheduleLocalNotification:localNotification];
受け取りは `- application:handleActionWithIdentifier:forLocalNotification:completionHandler:` メソッドが呼ばれます。
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler {

    if ([identifier isEqualToString:@"ACCEPT_IDENTIFIER"]) {
        // ...
    } else if ([identifier isEqualToString:@"MAYBE_IDENTIFIER"]) {
        // ...
    }
    if (completionHandler) {
        completionHandler();
    }
}

まとめ

Push 通知に選択肢を付けられるようになったことで、通知からアプリを開く以外に任意の動作を行わせることができるようになりました。
例えば簡単なアンケートであれば Push 通知から答えてもらうなどもできそうですね。(Yes or No)

しかしバナー表示の場合は選択肢があることに気付きにくいので(通知を引っ張る、スワイプ)、アプリ内のチュートリアルなどで選択肢付きの Push 通知が届くこと、選択肢はどのようにして表示させるのか、ユーザーがわかるように伝える必要がありそうですね。

今回使用したサンプルコードは AppDelegate だけですが gist で公開しております。
Xcode で Single View Application でも何でもプロジェクトを作成し、AppDelegatem.m にコピペしてもらえればと思います。
Parse を使用していますので、アプリケーション ID などは別途設定してください。

あなたにおすすめするたった一つの最高のキーボード

みなさまこんにちは!

VOYAGE MARKETINGにてエンジニアをしている@gomachan46です。
社内の非公式サークルとして音ゲー部なるものを立ち上げて日々熱心に活動しております。


さて、みなさまキーボードはどのようなものをお使いでしょうか?

エンジニアな読者のみなさまは、キーボードには特段の思い入れがあるのではないでしょうか。

そこで、VOYAGE GROUPのエンジニア達がどんなキーボードを使っているか見てきました。 

realforce

高級キーボードの代名詞的なREALFORCEや、

hhkb

矢印キーのない非常にコンパクトなHHKB

kinesis

エルゴノミクスデザインが斬新なKinesis

truly

エルゴノミクスキーボードスレで定番と噂のTruly Ergonomic

打鍵音が良い、打鍵時の感触が良い、コンパクトでどこでも持ち運べる、変荷重で各指に合った程よい重さ、、、などなど色々あることと思います。

僕も例に漏れずキーボードは人一倍こだわって選んでいます。

そこで今日は僕のキーボードを紹介したいと思います!

otoge


どうでしょうかこの重厚感!他とは一線を画すデザイン!高級感あふれるメタリックボディ!
そしてなんといっても左側に燦然と輝くturn table!!

素晴らしいの一言に尽きますね。

■ What is this?

音ゲー用のコントローラーです。

■■ What is Otoge?

簡単にいうとリズムに合せて作成された譜面の通りにボタンを押して遊ぶゲームです。
 
otoge_info

 
一般的に失敗(Failure)、成功(Clear)に結果が分かれ、更にClearの先にはミスのないフルコンボ(FullCombo)という結果もあります。

こんな音ゲー用の代物なので、僕のキーボードは打鍵感、打鍵音ともに折り紙付きなキーボードなのです。

■ Let's Programming!

せっかくなので素晴らしさを伝えるべくこのキーボードでプログラミングしていこうと思います。

otoge2

これらのボタンにキーバインドをしていき、キーボードとして機能するようにします。

■■ Hello World!

プログラミング言語はRubyです。 

puts 'hello world'

これをRubyを対話的に実行できるirbを起動して実行するところまでをやってみます。

実際にプログラミングしている様子がこちらになります。



いかがでしょうか。実に楽しそうですね!

■ From now on...

このように、これからの時代はまず譜面を作り、それをプレイすることで開発を行う譜面駆動開発(Fumen Driven Development)が主流となっていくことでしょう。
Failed->Clear->FullComboの黄金サイクルを回すことで、開発にリズムが生まれ、進捗最高になること間違いなし!

いかがでしょうか?
みなさんすぐにでも今お使いのキーボードから乗り換えたくてウズウズしているのではないでしょうか。

さぁ、今すぐFDDを始めましょう! 

Socket.IO サーバーを Haskell で書いて Yo っぽいものを作ろう

こんにちは。adingo で広告配信のお手伝いをしている井手上です。
今回のエンジニアブログは Haskell の Socket.IO サーバーライブラリを使って、Yo みたいなアプリケーションを作成した話です。

前置き

突然ですが、皆さんはお仕事や個人的な開発ではどんなプログラミング言語・ミドルウェア・プラットフォームを利用していますか?
 
Web アプリケーションを作るなら Python や Ruby 等のいわゆる Lightweight Language、大量のリクエストを高速に、並列に処理したいのなら Erlang など、目的に応じた選択肢があると思います。色々な選択肢がある中、以前は最適だと思って選択したものが、年々新しい技術がが出てきているために今ならもっと良い選択ができるという状況になることもあるかと思います。

私が働いているチームでは採用ページの「業務内容」に書いてあるとおり「合理的な理由がありチームにとって受け入れ可能であれば別な技術の採用や別な技術へのリプレースを拒む理由はありません」ということで、新しい技術での開発やリプレースがよく行われています。最近ですと、Perl で書かれていた広告配信システムの一部機能を自由に高速化するコンペを行い、優勝したシステムを採用するという取り組みを行い Golang 製のシステムが優勝しました。自分も最近始めた Haskell をどこかに投入してやろうと虎視眈々と狙っているところです。

その Haskell ですが、実際に投入するかどうかはともかく、関数型プログラミングや型システムといった多くのプログラミングパラダイムを学べるお得な言語です。自分が知らないパラダイムを学ぶことは問題の捉え方や問題解決のための選択肢を増やすという点で役立ちます。今回は、Socket.IO 1.0 サーバーの Haskell 実装が出てきたということで使ってみました(前置きが長い)。

Socket.IO 1.0


Socket.IO はクライアントとサーバーとのリアルタイム通信を実現するフレームワークです。チャットアプリケーションやドキュメントの共同編集機能のように、リアルタイムなやりとりに利用されます。クライアントには主にブラウザが挙げられ、通信プロトコルには WebSocket を利用しています。Socket.IO は 2010 年からあるようですが、2014 年 5 月に Socket.IO 1.0 となりました(GitHub リポジトリのコミット履歴より)。

個人的に Socket.IO 1.0 で面白いと感じている点は、大きく分けてモジュールが Socket.IO と Engine.IO に分かれている点です。Engine.IO はトランスポート層のプロトコルの違いを吸収することに責任を持ちます。Socket.IO には Engine.IO よりもアプリケーション寄りの高レベルな機能が実装されており、自動再接続や名前空間機能を提供しています。

Engine.IO でのトランスポート層プロトコルの違いを吸収する方法について簡単に説明しますと、接続開始時は接続できる可能性が高いロングポーリング方式で通信を開始し、WebSocket での通信が可能ならば、WebSocket に切り替えるというように、upgrade していく方式でトランスポートの違いを吸収しています。WebSocket 接続のタイムアウトを待ってロングポーリングに切り替えるというような fallback 方式ですと、最初はつながらないので、WebSocket を使用できないユーザーにとっては接続までが長くてイライラしてしまうかもしれません。upgrade 方式だとはじめから接続できるので、ユーザー体験は fallback 方式よりも悪くないことが期待できます。
 
ocharles/engine.io

Socket.IO というと、公式の提供しているサーバーが Node.js 製なので、サーバーも JavaScript で書くイメージがありますが、プロトコルさえ実装されていれば良いので、サーバーは Node.js でなくても構いません。今回使用する ocharles/engine.IO は Socket.IO 1.0 を Haskell で実装したサーバーになります。

Node.js よりも Haskell でサーバーを書くことの良い点は、期待しているデータの型を定義しておけば JSON のパース時にデータのチェックを行う必要がないというところかなと思います。

下記の例は addPerson というメッセージがきたときに、data に name と age というプロパティが存在するかチェックしている例です(JavaScript版)。age は数値を期待されているはずなので、数値であるかどうかのチェックまで必要かなと思ったり心配事は多いです。 


次は同じ例の Haskell 版です。addPerson メッセージがきたときに JSON データを Person データ型に変換する処理が入ります。その時に name や age が存在するか?フィールドの型として正しいか?というようなことがチェックされます。データ型を定義しておけばその定義に沿わない JSON はパースできないので、パースとデータのチェックが同時にできます。


上記の例を比較してみると、JavaScript 版の方がコード量は少なくカジュアルに書けそうですね。アプリケーションが行う通信でのインターフェースをしっかり決めて、それが複雑であったり、データのチェック項目が多い等の場合は Haskell でサーバーを書くのもありかもしれません。

KaitenZushi


今回は Socket.IO を使ったアプリとして、KaitenZushi という Web アプリケーションを作ってみました。これは最近話題になった Yo というアプリを意識しています。Yo は誰かに「Yo」というメッセージを送るだけのシンプルなアプリです。例えば朝方に Yo と言われると、(たぶん)おはようの意味だったりと、人同士の関係や時間等々の様々なコンテキストを考えて、Yo を受け取った側が何となく解釈するという大変ハイコンテキストなアプリです(自分の理解では、ですが)。

KaitenZushi はもう少しコンテキストを絞ったらどうなるのかな?という考えで作りました。右上の入力ボックスからコンテキスト(コンテキスト = 寿司ネタをイメージしてます)を作成して、寿司(コンテキスト)を、同じコンテキストにいる人たちにブロードキャストできます。なかなか用途がわからないアプリだと思いますが、自由に寿司を配ってみてください。

KaitenZushi のリポジトリは以下になります。サーバー側のコードはとても短く、寿司がサーバーに emit されたら、接続している人全員に寿司を broadcast するという機能だけです。


ちなみに今回は Node.js で Haskell 版と同じ機能を実装して heroku 上にデプロイしています。ocharles/engine.io は Snap や Yesod といった Haskell 製の Web アプリケーションフレームワークにも対応しており、heroku もそれらに対応しているのですが、今回は時間の都合上、サクッとデプロイできた方を使用しました。

まとめ

Haskell の勉強ついでに KaitenZushi という Socket.IO 1.0 を利用した Web アプリケーションを作ってみました。まだまだ道半ばですが、自分の知らないプログラミングのパラダイムを学ぶことは楽しいです。

最後に、弊社には ajito という社内バーがあり、エンジニアが夜な夜な出現してビールを飲んだり技術的な話をしたりと楽しい場になっています(#ajiting といいます)。弊社エンジニアに一声掛けてくださると、無料でビールを飲みつつ歓談できるかと思います。また、勉強会の場としても提供していたりするので、どんどんお声掛けください!そして、KaitenZushi にも ajiting のコンテキストを作ったので、いらっしゃった時には使ってみてください!

参考
記事検索
QRコード
QRコード