読者です 読者をやめる 読者になる 読者になる

メディアフォース 開発者ブログ

株式会社メディアフォースの開発者による非公式ブログです。

DataSpider DevConn ハッカソン開催!

新年明けましておめでとうございます。*1

当社とお付き合いも長く、当ブログでも名前がよく挙がりますアプレッソさん とこの度、3月にハッカソンを開催する運びになりました。

その名も

DataSpider DevCon Hackathon

dstn.connpass.com

DataSpider の新製品である DataSpider Cloud がリリースされたことを記念してDataSpider をお使いの方も、検討されている方も、初めて聞いた方も、DataSpider Cloudに触っていただきつつ各種APIと連携し、未来の何かを作ろうという企画です。

DataSpiderを触ったことがない方、当社現役エンジニアがサポートいたしますのでご安心ください。

connpassには載ってませんが優秀な作品には各社から賞品が出るとか出ないとか。

是非この機会に当社のエンジニアとDataSpider Cloudを使った連携システムを開発してみていただければと思います。

*1:あけて一発目なので。。。

Pepperくん秘書化計画 ~スケジュール編~

Zenfone 3につづいて Zenbook 3 を発売日に購入したメディアフォース齊藤です。
Zenfone 3 Laserを購入しようか迷ってます。

本記事はアプレッソ Advent Calendar 2016 の16日目の記事です。
qiita.com

去年も書かせていただいてますが、偶然にも 同じく16日でした。

スクリプト開発時に気をつけるべき3つのポイント - Appresso Engineer Blog

毎年12月16日は齊藤の日として広めて参りたいと思います。

Pepperくん秘書化計画とは

さて、Pepperくん秘書化計画についてご説明しましょう。

みんなだいすき顔面蒼白のPepperくんですが、説明係だったり案内係だったりとめんどくさい客来客対応として使われるケースが多いように思います。

Pepperくんを個人で購入される方はあまり多くはないと思いますが、なかなかに値が張ります
せっかくなので自分のために使いたい!ということでPepperくんには秘書として存分に働いてもらおう計画です。

構成図

f:id:mf_sol_eai:20161215110923p:plain

  1. Pepperくんに教えを乞う
  2. PepperくんがDataSpider Cloud(以下、DSC)にHTTPリクエスト飛ばす
  3. DSCがGoogle API経由でスケジュールを取得
  4. DSCでスケジュールをセリフ状のテキストに整形し、レスポンスボディで返す
  5. Pepperくんが受け取ったテキストを喋る

やろうと思えばPepper -> Google APIの直接でも出来ると思うんですが、GoogleのOAuth2認証やテキスト整形がめんどくさかったので簡単にできそうなDataSpiderを利用しました。
ちなみにDSCはまだリリースされていないので、DSC想定で普通のDataSpiderをEC2に置いてある感じです。

Google APIを取得する

DataSpiderによるGoogle API連携についてはこの記事を参考にしてます。
DataSpider RESTアダプタを使ってGoogleカレンダーの予定を取得する。 - Qiita

記事からちょっと変えた点

  • 認証情報の「APIを呼び出す場所」をその他のUIに変更してます。

f:id:mf_sol_eai:20161215112414p:plain

この場合、リダイレクトURLは不要ですが、http://localhost:7700 を指定しておきます。

また、最近 Google アカウントは二段階認証を導入しましたが、検証時点では二段階認証があると認証のレスポンスが受け取れなかったので無効にしてます。

DataSpider側のアプリをつくる

github.com

DSC_GoogleCalendar.zip に DataSpider プロジェクトを置いてあります。

  1. OAuth認証のグローバルリソースを作成しておく。
  2. 変数のcalendarIdに取得したいカレンダーIDを入れておく。カレンダーIDについてはここでは説明しないのでググってください。
  3. 実行すると、returnText にセリフ状のテキストが入ります。
  4. サービス登録し、HTTPトリガーを作成する。HTTPトリガーでreturnTextをレスポンスボディに含める設定にします。
  5. HTTPトリガーの設定が完了したら、ブラウザからHTTPトリガーにアクセスする。
  6. ブラウザにテキストが表示されたらOKです。

スクリプトの流れ

f:id:mf_sol_eai:20161215130754p:plain

  1. Google APIでカレンダーを取得する
  2. Mapperを使ってサマリ、開始日時、終了日時を取得する。
  3. 一旦CSVに吐いておく
  4. 吐いたCSVを読んでPepper用テキストに整形する。

Pepperアプリ

Pepperアプリの開発にはChoregrapheを使っています。
Pepperは「今日のスケジュール」といったワードに反応してスケジュールを教えて欲しいところです。

  • Choregrapheプロジェクト全体像

f:id:mf_sol_eai:20161215131049p:plain

ということでChoregrapheプロジェクトはPepper_DSC.zipに置いてます。

プロジェクトの構成

  1. Speech Reco. で「今日;明日;ありがとう」を登録しておきます。「今日」と「明日」でそれぞれのスケジュールを通知し、「ありがとう」で終了します。
  2. TextEditの「DataSpiderのURL」には先程ブラウザで確認したURLを設定しておきます。
  3. HTTP Getはこちらの記事を参考にしていますが、変えた部分があるのでコード全文載せておきます。
class MyClass(GeneratedClass):
    def __init__(self):
        GeneratedClass.__init__(self)

    def onLoad(self):
        #put initialization code here
        pass

    def onUnload(self):
        #put clean-up code here
        pass

    def onInput_onStart(self, url):
        from HTMLParser import HTMLParser
        import urllib2, contextlib

        class ContentParser(HTMLParser):
            def __init__(self):
                HTMLParser.__init__(self)
                self.inscript = False
                self.inbody = False
                self.text = ""

            def handle_starttag(self, tag, attrs):
                if tag == "body":
                    self.inbody = True
                if tag == "script":
                    self.inscript = True

            def handle_endtag(self, tag):
                if tag == "body":
                    self.inbody = False
                if tag == "script":
                    self.inscript = False

            def handle_data(self, data):
                if self.inbody and not self.inscript:
                    self.text = self.text + data

        try:
            timeout = int(self.getParameter("Timeout"))
            self.logger.info("Loading... %s" % url)
            response = urllib2.urlopen(url)
            text = response.read()

            self.logger.info("Loaded: %s" % text)
            self.onStopped(text)
        except urllib2.URLError, message:
            self.logger.warn("Failed to open: %s, message=%s" % (url, message))
            self.onFailed(message)

コードはやっつけですみません。。。

デモ

中々おもしろい感じにできたんじゃないでしょうか

あいだにDataSpiderを経由することで実装がやや難しい認証周りが比較的簡単に実装できたり、DeepLearningに学習用データも一緒に登録したりもできたりするのでPepper単体で完結できるものでも挟んでおくと色々はかどりそうですね :D

第二回社内LT大会リンク

先日、社内ハッカソン&LT大会を開催しました。

mf-sol-eai.hatenablog.com

せっかくなのでLT資料をあげたいと打診してみたところあげてもいいよ!って方がいたので、Slideshareのリンク集にしました。

LTリンク

AngularJS 触ってみたファーストインプレッションについて

www.slideshare.net

おすすめのサービスエリア・パーキングエリア(関東編)

www.slideshare.net

茨城県民魂の叫び

www.slideshare.net

プリン体はほどほどに

www.slideshare.net

愛車をJavaモデリングした人(謎)

www.slideshare.net

prezi初挑戦
Bootstrap入門

www.slideshare.net

第三回社内ハッカソン開催しました。そしてLT大会へ

全国のSIerの皆様いかがお過ごしでしょうか。

f:id:mf_sol_eai:20161204234236j:plain

ハッカソン

当社では定期的にハッカソンを実施しており、先月11/25に第三回ハッカソンを開催しました。 多少前後はあるものの、6人*6チームの36人程度に規模になります。

キックオフとチーミングタイム f:id:mf_sol_eai:20161204235908j:plain 衝立の向こう側ではえらい人達も見学に...

テーマは「身近な業務改善」ということで、各々様々な業務に対して改善を提案していました。 SIerと言えばプログラミングをしてるイメージがあると思いますが当社では、配属先によって事業内容が大きく変わることもあり、プログラミングに拘らずチームによって得意な手法を用いてました。

筆者がPepperにハマっていることもあって当チームはPepperにフォーカスした開発を。 f:id:mf_sol_eai:20161204234832j:plain

テーマ:Pepper秘書 f:id:mf_sol_eai:20161204235656j:plain

1年目の若手から10年超のベテランまで一緒に作業中 f:id:mf_sol_eai:20161205000510j:plain

そして今回は、ファイル転送ソフトHULFTで有名なセゾン情報システムズ様からもご参加いただいたこともあり、DataMagicを活用していたチームもありました。

また、さらに来年入社予定の内定者も数名お招きしてハッカソンを体感してもらいました。 研究などでプログラミングをした経験がある方もいましたが、現役の開発者と開発する経験は良い刺激になったんじゃないでしょうか。

はい、そして終わったあとは懇親会です。 f:id:mf_sol_eai:20161204234343j:plain チームの皆との乾杯はまた格別ですね。

そしてLT大会へ...

今回はハッカソンだけではありませんでした。

懇親会中でLTやりたいと言ったところ、若手からベテランまで13名もの方が自分が発表したいと声をあげてくれました。 f:id:mf_sol_eai:20161205001041j:plain

せっかくなのでPepperくんに5分タイマーになってもらいました。 f:id:mf_sol_eai:20161205001140j:plain 5分経過すると罵声を浴びせながら中断させにかかります。

フリーテーマだったので、技術的な話から f:id:mf_sol_eai:20161205001248j:plain

サービスエリアの話まで f:id:mf_sol_eai:20161205001336j:plain

技術者としては、こういう場でドヤ顔しながら開発するのが一番楽しいですよね

LTリンク

LTまとめました

mf-sol-eai.hatenablog.com

LTってやっぱ面白い。そしてprezi難しい。

先日、当事業部内で懇親会を行ったのですが、ふとLT大会をやりたくなったので有志を数名集めてLT大会を実施しました。

若手の懇親会の場だったのでLTを知らない方も多く、ざっくりとLTとはなんなのか + オーディエンスも盛り上げてね的な意味を込めて(とはいえ Reveal.js と github.io を使ってみたかっただけという)頭出しスライド作ったのでうpしておきます。

たのしいLT祭り

懇親会でのLTということで、ノンテーマで実施したので技術的要素は限りなく薄め。 アニメの名言やらナンパ術やらをとくと語る中々濃い時間。 そして楽しみすぎてLT大会の写真は一切ないという・・・。

あと prezi も使ってみたかったので preziでやってみた。

IT昔話

preziはとても難しいという*1ことがわかったので成果は上々。パワポマンにはスタイリッシュなプレゼンは出来ないよパトラッシュ...

無論、内容を問われるLTもあると思いますが社内でやる場合など軽いLTの場も多くあると思うので、エンジニアの方々には是非とも自分を見せる場を活用していって欲しいですね。

*1:未完成品なのでいつか完成させたい...

JavaSEでCDIのObserversを試してみる

利用方法

今回は、JavaSEで使ってみたいと思います。
話し変わりますが、JavaEE7 から色々なライブラリの仕様取り込んだりしてEJBが駆逐されつつあっていい感じに見える。

事前準備

  • お好みでeclipseなど。
  • Weldを落としてくる。
    • ここ からダウンロードできる。
    • Mavenの場合
<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se-core</artifactId>
    <version>2.4.0.Final</version>
</dependency>
  • パスの通っている場所にMETA-INFディレクトリおよび空のbeans.xmlを作る。
  • 今回使ったプロジェクトはこちらにうp github.com
  • src配下にMETA-INFディレクトリ作ってあるけど良くない気がする。(サンプルだしまぁいいか)

何ができるんじゃろか

@Observers アノテートされた引数の型とEventの型が一致した場合に勝手に通知してくれるっぽい。

試してみる

java:ObserverSample.java(通知用)

public class ObserversSample {
	@javax.inject.Inject
	javax.enterprise.event.Event<User> event;
    
	public static void main(String[] args) {
		Weld weld = new org.jboss.weld.environment.se.Weld();
		WeldContainer container = weld.initialize();
		ObserversSample obsSample = container.instance().select(ObserversSample.class).get();

		obsSample.run();
	}

	public void run() {
		this.event.fire(new User().name("山田").age(30));
	}
}


java:User.java

public class User {
    //単なるPOJOなのでgetter/setterは省略
	private String name;
	private int age;
}

java:UserEventListener.java

public class UserEventListener {
	public void fire(@Observes User user) {
		System.out.println("Event Fire:" + user.getName());
	}
}

実行すると

Event Fire:山田

が出る。Eventを介して見事に通知された。楽すぎる・・・。

通知先を指定する

せっかくなので、InsertイベントとUpdateイベントで分けたい。
今のままだと、Insert用UserクラスとUpdate用Userクラスを作るか、Userクラスの中でイベントタイプを持つかしないとならないのでちょっとイケてない感がある。

ということで、Qualifier を作る。

アノテーションなので @interface で定義する。

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Insert {}

Eventに @Insert アノテーションを付ける。

public class ObserversSample {
	@Inject
	@Insert
	Event<User> insertEvent;

	public void run() {
		this.insertEvent.fire(new User().name("山田").age(30));
	}
}

EventListener の引数に @Insert を付与する。

public class UserEventListener {

	// @Insertあり
	public void insert(@Observes @Insert User user) {
		System.out.println("Insert:" + user.getName());
	}

	// @Insert無し
	public void any(@Observes User user) {
		System.out.println("Any:" + user.getName());
	}
}

実行してみる

Insert:山田

@Insertのメソッドのみが通知され、@Insertなしは通知されない。

通知されたメソッドで例外が発生すると、呼び出し元に例外がthrowされてそれ以降は伝播しないもよう。

キャリアプランを考える ~1. 自分コンセプトを決める~

夏の暑さも落ち着き秋の涼しさも感じられるようになった昨今、いかがお過ごしでしょうか。

9月ともなると就職活動に励む学生が目立ちますね。当社でも数年前から新卒を精力的に受け入れており、最近では中途採用より新卒採用のほうが比率が高くなってきました。

さて、当事業部でも新卒者を受け入れますが、中途採用と違って新卒者はキャリアプランを決めきれてないケースが多く見られます。 就活シーズンということで、キャリアプランについてお話したいと思います。

キャリアプラン

就活生にとって就職とは金銭を稼ぐ手段を得るためのものであると思いますが、学生の期間は20年前後であるのに比べ社会人の期間は40年以上もあります。 是非とも学生のうちからキャリアプランを考えておき有意義な社会人生活を送っていただければと思います。

キャリアプランについてはググれば多々でてきますので、そちらも併せて参照いただくとして筆者個人の定義としては次のように考えてます。

続きを読む