今日のつちや

お疲れ様でした

技術書典4で同人誌を出すために「ワンストップ!技術同人誌を作ろう」を読んだ(良かった)

@corocn ですこんにちは。

技術書典4 の申込みが始まってますね。

今年は技術系同人誌を書いてアウトプットすることを目標に掲げたのですが、同人誌を書いたことのない私にとっては、何をやっていいか一切分からない状態です。(出版に関する知識がマジで無い)

そこで出会ったのがこの本

ワンストップ!技術同人誌を書こう - oyakata - BOOTH

コミックマーケット93で頒布されたやつですね。BOOTHで電子版を買いました。 結論から言うと最高だったので、初めて書くぞ!って人は読むと良いと思います。

200ページぐらいあるので、ざっと流し読みして、あーこんなことを気に留めておく必要があるんだーなるほどー!ぐらいのノリで読んで、詰まったときにじっくり中身を読むのが良さそうです。

以下ざっと読んだ感想。

感想

  • 当落関係なく書くつもりでやる。落ちたら委託すればいい。アウトプットに意味がある。
  • 印刷方法にはオフセットとオンデマンドがあるが、初めての人はオンデマンドで出すのが良さそう。
  • サイズはB5が主流。
  • Macヒラギノは商用利用可。
  • 原稿はGithubで管理すると良さそう。
  • 執筆ツールは色々あるが、Re:VIEW が良さげ。
  • 出力はPDF前提でやると、電子書籍で配布するのも捗りそう。
  • 表紙はオマージュ系、イラスト系、フリー素材系に別れそう。
    • たまたまお願いできる人がいたのでイラスト系にする。
    • 頼める人がいなかったらフリー素材にしたと思う。
  • 表紙はKeynoteで作るのが良さそう。
    • Keynoteは最高の作画ツール。
  • 画像は印刷用に300dpi以上で出すが、電子書籍はサイズが大きくなるので、解像度を少し下げる。
  • 確認用の連番としてノンブルというものがある。
  • ページ数は4の倍数にすべし。
  • プリンターはあったほうがいい。
    • 以前会社の人と話してて、「最近プリンターなんて必要なくない?」なんて言ってすいませんでした。要るわ。
  • PDFの入稿は同人誌業界ではマイナーだけど、技術系だと多いみたい。
  • トンボ・塗りたし。 指定の塗りたしを含めた「正しい」PDFの入稿が必要。
  • 横書きの技術書は左綴じ。
  • CMYK形式での変換を行って入稿するのが原則。
  • 直接搬入が一番楽。
  • ポスター作ったほうがいい。キンコーズなどで作れる。
  • 早割を締め切りにする。完成形の出力まで1回通しでやってみておくのが良い。
  • 当時は2万円分ぐらいを両替して持ち込む。必要なものの確認もスケジュールに含める。
  • 個人名刺を作らねばという気持ち。
  • 電子決済の話がないように思えたので、あとで調べておきたい。何が良いんだ?

上記トピックでも足りてないと思うので、スケジュールをはやめに決めたいですね。で、スケジュールを決めるためには印刷所の締め切りを考慮する必要があるので、まずは印刷所を決めようと思います。技術書典との連携が厚いところを選ぶつもりです。

これも大事だよってのがあれば、教えて欲しさ。 あとは会社の人の出版経験があるから、頼らせて貰うつもり。

以上、参考になれば!

追記

https://techbookfest.org/event/tbf04#guide によると

日光企画、ねこのしっぽ利用の場合、印刷所からの直接搬入が可能です。

とのことなので、2択な気がしてる。

2017の振り返り

新卒で就職したコッテコテの古き良き日本大企業から転職を決意して、今日で1000日経過した。

f:id:corocn:20171231152733p:plain http://counting.hatelabo.jp/count/rk959zjrfl(勝手に作られてた)

転職した

これが一番大きなイベントだった。

東京の会社も色々見に行ったけど、人混みが辛くなったのと、色々あって結局地元に落ち着いた。

昔大手の転職サイトに登録したら、やたらと電話がかかってきて死ぬほどダルい思いをしたので、 今回はWantedlyのみで転職活動していた。

たまたま貰ったスカウトメールの会社を見たら、 Twitterでフォローしてた雪うさぎのアイコンの人がいて、興味を持った(Twitter初期からフォローしていたけど、一切面識が無かった)

採用プロセスがかなりユニークで、トントン拍子で入社することになった。 そしてMisocaというクラウド請求書の会社にいる。かなり働きやすい会社だと思う。社員も人格者が多い。

勉強した

残業ゼロで時間が取れるようになったので、気になっていた技術で遊んだ

Ruby, Rails

  • 実は今の会社に入るまでは、PHPがメインの開発言語だったので、少し業務でRailsを書いた程度だった。 (なんで採用してもらえたか謎だけど、Computer Scienceのバックグラウンドがあるのは大きいのだろうか。)
  • がっつりRubyを書くようになって、虜になった。
  • RailsはWebpackerがカオスなので、最近はNuxt.js + Rails API Modeが良いんじゃないかと思ってる。

JavaScript, Vue.js, Nuxt.js

  • モダンジャッバスクリプトのナウい書き方が未だに分からなくて未だに困惑している。
  • JavaScriptをビルドするのが辛い。型の無い言語をビルドするのに抵抗がある。
  • React+Reduxを触ってきたけど、Vueのほうがしっくりきていて、Nuxt.jsがマジで良い。

AWS

  • 業務でも使うので色々触った。
  • サービス増えすぎて追いかけるが大変ではあるが、テクニカルサポートが手厚くて便利。
  • BlackBelt Dojoを会社で実施してもらうと凄く捗る。
  • 細かく設定できる分、個人ベースでさっと使うのには向いてない感じはある。

勉強会

  • フロントエンドもくもく会に参加してて、運営を手伝わせて貰っている。
  • 年明けにはLT大会もあるので楽しみ。

来年

  • 前のめりでやっていく
  • 新しい言語を学ぶ(Kotlinあたり)
  • 本を書きたい(技術書店に出したい)
  • 結婚したいです

今年もお世話になりました。 来年もよろしくお願いします。

Google HomeでTech系Podcastを聞く(Dialogflow + Cloud Functions編)

こんにちは、@corocnです。 今回は音声認識マンらしく話題のGoogle Homeを触ってみました。

Misoca Advent Calendar 2017 - Qiita の14日目の記事になります。

はじめに

最近は、Google HomeでTech系のPodcastを雑に聞きたいなぁという欲求があって、色々と試しています。

現状考えられるアプローチとして3つありまして

  1. Google Play Musicに音源を放り込む
  2. 専用のストリーミングサービスを作る
  3. Dialogflow + Cloud Functionsで音源を再生する (今回の記事)

1はコレじゃない感、2はそもそもが作り方が謎でして、「キーワードに反応して特定の音源が再生できれば何でもできるやろ」ということで、3番目を試した記事になっています。IFTTTは使いません。

rebuild.fmが聞きたいのが始まりだったのですが、Google Homeで再生可能な音源なら何でも適用できるはず。

既に色んな方がDialogflowの解説記事を出してくれていますが、それらを見た上でハマったポイントも掲載して、初心者向けチュートリアルしてまとめてみました。

Dialogflow

f:id:corocn:20171211215525p:plain

対話ボットを簡単に作成できるサービスになります。 自然言語対話プラットフォーム「API.AI」が、Googleに買収されたことで、名前を変えました。

https://dialogflow.com/

Dialogflowでは、プロジェクトを「Agent」という単位で管理します。以下の機能を使ってボットを作ります。

  • Entities: 会話に含まれるキーワードを定義
  • Intent: 会話の流れを定義
  • Fulfillment: SSML(後述)を生成するサーバーをWebhookで指定
  • Integrations: デプロイ

※ この先、Googleから許可を求められたら内容を確認の上、承諾して進めてください

Agent

左上のCreate new agentから作成できます。

f:id:corocn:20171211213728p:plain

作成画面が出るので、諸々の情報を入力してください。今回はpodcast-playerという名前にしてます。

V2 APIはbetaなので、今回はV1で試します。有効にしないでください。 (´-`).。oO(今度V2 APIの解説も書けたらいいな...)

f:id:corocn:20171211213744p:plain

Entities

Agentの作成ができたところで、Entitiesを定義していきます。

@podcast_name を @action して

という文章で実行する予定ですが、@podcast_name, @actionがEntityになります。それぞれキーワードと言い換え語を入力します。

f:id:corocn:20171211213801p:plain

f:id:corocn:20171211213813p:plain

f:id:corocn:20171211213825p:plain

登録できました。

Intent

Entitiesが定義できたので、Intentを作成します。 ちょっとクセのあるUIですが、

まず「podcast_nameをactionする」と入力して追加

f:id:corocn:20171211213837p:plain 追加された1文のEntityをマウスで範囲選択するとキーワードを適用できます。@podcast_nameでフィルタすると早いですね。@actionも同様です。

f:id:corocn:20171211213855p:plain 紐付けが終わるとUser saysとActionが自動で埋まります。

いくつかパターンを定義していきます。

f:id:corocn:20171211213910p:plain

保存の前にActionを必ず入力してください。 忘れがちですが、入れておかないと今後の処理で困ります。「play.podcast」にでもしておきます。

f:id:corocn:20171211213923p:plain

これで保存して完了です。

Fulfillment

最後にWebhookの設定をしたいのですが、この段階ではレスポンスを返す環境を用意してないので、適当なdummyにしておきましょう。

保存後、先ほど作成したIntentを見ると、ページの下部にFullfillmentの設定が追加されているはずなので、Webhookを有効にしておきましょう。

f:id:corocn:20171211213932p:plain

f:id:corocn:20171211213940p:plain 保存をお忘れなく。

SSML with Cloud Functions

Google HomeはSSML(Speech Synthesis Markup Language)という形式に対応しており、特定のキーワードに反応させて別途用意したサーバーからSSMLを返すことで、任意の発話やアクションを実行することができます。

今回はCloud Functionsを使って、簡易的なレスポンスサーバーを用意して試します。

SSML

詳しい文法は OfficialActions on Google(Google Home)で使用できるSSMLタグのまとめ | KOTODAMA TODAY を見ると良いと思います。

とりあえず凝ったことはせず、固定のURLの音源を再生する方針で進めます。

<speak>
 リビルドエフエムを再生します。
 <audio src="https://hoge/sample.mp3/"/>
</speak>

srcはHTTPSのみ対応しているので注意してください。

上記例では、sampleにしていますが、テスト時はS3とかCloud Storageに雑にファイルを置いて試していました。直リンでやると怒られると思いますので、自分で用意してみてください。

サンプルサーバー

以下をクローンして、functions/index.jsを書き換えます。 https://github.com/actions-on-google/dialogflow-webhook-template-nodejs

'use strict';

process.env.DEBUG = 'actions-on-google:*';
const { DialogflowApp } = require('actions-on-google');
const functions = require('firebase-functions');

exports.yourAction = functions.https.onRequest((request, response) => {
  const app = new DialogflowApp({request, response});
  console.log('Request headers: ' + JSON.stringify(request.headers));
  console.log('Request body: ' + JSON.stringify(request.body));

  // Fulfill action business logic
  function responseHandler (app) {
    // Complete your fulfillment logic and send a response
    app.tell({
      speech: '<speak>リビルドエフエムを再生します。<audio src="https://hoge/sample.mp3"/></speak>',
      displayText: 'さいせい'
    });
  }

  const actionMap = new Map();
  actionMap.set('play.podcast', responseHandler);

  app.handleRequest(actionMap);
});

app.tellのspeechのvalueにSSMLを直接記述できます。

actionMap.setのキーを、Intentで設定したaction名に変更することをお忘れなく。

また、サンプルのmp3は適宜書き換えてください。

Deploy Webhook

firebase へでデプロイします。

firebase-toolsが必要なので、この辺を参考に入れると良いです。 https://firebase.google.com/docs/hosting/deploying?hl=ja

以下のコマンドを順に実行して、deployします。

# functions以下でnpm install or yarn installが必要
$ cd functions
$ yarn install
$ cd ..

# firebaseへログイン
$ firebase login

# firebaseを初期化
$ firebase init

? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choices.
> ◯ Functions: Configure and deploy Cloud Functions

? Select a default Firebase project for this directory:
> podcast-player

✔  Firebase initialization complete!

# deploy実行
$ firebase deploy --only functions

Function URL (yourAction): https://us-central1-xxxxxxxxxxxxxx.cloudfunctions.net/yourAction

✔  Deploy complete!

最後にfunction URLを教えてもらえるので、コピっておきます。 なお、そのまま叩くと「Action Error: no matching intent handler for: null」というエラーが出ますが、正常です。

Fulfillmentを修正する

ここでDialogflowのFullfillmentへ戻って、dummyのURLを、先ほど生成したFunction URLへ変更しておきましょう。

f:id:corocn:20171211214001p:plain

Integration

さてさて、準備が整ったので、DialogflowのIntegrationsから、Google Assistantを選択してテスト環境へ反映していきましよう!

といっても、Additional triggering intentsで、作成したintentsを選択し、UPDATE DRAFTを押すだけです。

f:id:corocn:20171211214010p:plain

「Actions on Google draft successfully updated」と表示されたら成功です。VISIT CONSOLEからアプリの管理ページへ飛べます。

テストしてみる

諸々準備が終わったので、実際に動かしてみます。

Assistant app

VISIT CONSOLEを押すとAssistant app draftに飛んでくるはずです。

② App InformationのEditを押して、Assistant app nameと、その発音を入力します。 ここで入力した情報を用いて、Google Homeからアプリを呼び出します。

f:id:corocn:20171211214020p:plain

すごく適当ですが、こんな感じです。Pronunciationが他のアプリと被ると怒られます。

保存したら、1個前のページに戻ってください。入力が足りない的なエラーが出ているかもしれませんが、本申請するわけではないので、気にしないでおきましょう。

ページ下部のTEST DRAFTボタンでシミュレーターを起動します。

シミュレーターテスト

少しハマったポイントです。 本来なら、以下のようなやりとりをすると音源が再生されるはずなのですが、現状シミュレーターだと上手く動かないようです。

f:id:corocn:20171211214030p:plain

VALIDATION ERRORSに、 「UnparseableJsonResponseAPI Version 2: Failed to parse JSON response string with 'INVALID_ARGUMENT' error: ": Cannot find field.".」と表示されていました。どうやらV2 APIの形式でリクエストを投げているようで、シミュレーター上でV1 APIで試す方法がわかりませんでした。設定があるのかもしれませんが、よく分からず。

実機テスト

シミュレーターで動かなかったので、実機で動かしてみます。 自身のGoogleアカウントと紐付いている状態ですので、Google Homeから先程作成したテスト用アプリを実際に立ち上げることができます。

注意: 動画を再生すると、あなたのGoogle Homeが反応するかもしれません

上記動画ではs3にテスト用として置いたrebuild.fmのmp3音源を再生しています。 途中に長い無音区間が入っているのは、音声をロードしているためです。サイズが80MBほどあって、完全に読み込むまで再生が始まらないのが微妙ですね。

また、Play Musicのような音楽再生ではないので、1回停止すると再開できません。不便だ。。

まとめ

汎用性のないままこの記事は終わりますが、Dialogflow + Cloud Functionsで特定のURLの音源を再生してみました。

もう少し応用すればいい感じにできるんじゃないかな〜?と思ってますが、シークや途中再生が困難なので、PlayMusicにぶっこんだほうが便利なんじゃないのこれと思っています。

Cloud Functionsでゴニョれるので、なんでもできそうですね。今後も色々試してみようと思います。

GDCR17に参加してペアプロでLifegame作ってきた

こんにちは、@corocn です。 今年もAdvent Calendarの季節になってきました。今回はMisoca Advent Calendar 2017 の記事として書くことにします。

最近は、Teletype for AtomVisual Studio Live Share、AWS Cloud9などが発表されて、ペアプロの高まりを感じている今日このごろです。 今回は、2017/11/18に開催されたCodeRetreat @ 名古屋ギークバーに参加してきましたので、感想をつらつらと書こうかなと思います。

どんなイベント?

Lifegameを題材としたペアプロのイベントです。

実は夏頃にも同様のイベントに参加して、会社の開発ブログに参加報告を書きましたので、ルールなどは下記ブログを参照していただきたいです。

CodeRetreatに参加しました! 〜ペアプロのすゝめ〜 - Misoca開発ブログ

今回は、Global Day of Coderetreat 2017(GDCR2017) に参画していて、世界中で同時開催されるCoderetreatの1つとして開催されたのが特徴でした。

f:id:corocn:20171128212724j:plain

ルール説明中の写真です。

使用言語

私はRubyメインで参加しました。 参加者の使用言語の割合は、C#, Ruby, JavaScriptな感じでしたね。 特異な例としてExcel VBAがありました(後述) Lifegame初めて、ペアプロ初めて、という人が多くて慣れるまで時間がかかるようなイメージでした。

ご飯

会場のAdrianaさんは飯がうまい。スポンサー様ありがとうございます。 f:id:corocn:20171128212904j:plain

Excel VBA での発見

最初に組んだペアに合わせてExcel VBAで書くことになったのですが、これがなかなか面白かったです。 Excel!? VBA!? ウワッっと思うかもしれませんが、実は凄く良かったんですよ。(仕事で使うのはイヤですが)

Lifegameを書く時、私は以下のようなステップで実装することが多いです。

  1. セルのデータ構造を考える
  2. 初期値を適当に入れてみる
  3. 画面に描画する
  4. 次世代を計算するロジックを書く
  5. 計算した次世代を現在の世代として更新する
  6. ループして描画する

で、1セッションが45分なんですけど、初めてLifegameを書く人はルールを把握したいから4のロジックを書きたいのに、3の描画までで終わっちゃう人が多いんですよね。

しかしExcel VBAを使うと、

  1. セルのデータ構造を考える → エクセルのセルをそのままセルとして扱えば良い
  2. 初期値を適当に入れてみる → 黒く塗り潰した部分を生存としてすれば、初期値は塗るだけで良い
  3. 画面に描画する → できてる
  4. 次世代を計算するロジックを書く → ここを考えるだけでいい
  5. 計算した次世代を現在の世代として更新する → 複数シートをバッファとしてスワップすればできる
  6. ループして描画する → ロジックをループさせるだけ

ということで、ロジックを書くことに集中して、ざっくり雰囲気を掴んでもらうことができます。 初期値の設定も楽なので、色んなパターンを試してもらうこともできますね。

ペアの方が諸々初めての方でしたので、これで雰囲気掴んでもらうことができました。 そのペアは次セッションでGoogleのSpredsheetを使って実装していましたが・・・どうなったんだろう。

ツイートしたらお褒めの言葉を頂きました。

まとめ

5セッション脳みそフル回転で、結構ハードで疲れるイベントですが、楽しかったです。 次回はファシリテーションやってみようかなぁ。

明日は@eitoballさんがNGK2017の報告を書いてくれるようです。 参加したかったけど用事で参加できなかったので、楽しみにしています。

氷見で寒ブリを食らう

こんにちは、ころちゃん です。

どうしようもなく、寒ブリが食べたくなったので、寒ブリの聖地、富山/氷見まで行ってきました。 岐阜から富山まで高速で約3時間ぐらいです。意外と近いですね。

道中の、ひるがの高原SAは、ひるがの高原牛乳を使ったソフトクリームが抜群に美味いので、オススメです。 このクソ寒いのにソフトクリームを食べてる人が多くて笑います。

11月下旬なので、雪景色が見えますね。

昼飯

きときと寿司という回転寿司屋があるのですが、新鮮で美味い寿司が安く食べれます。

f:id:corocn:20171125172119j:plain

氷見きときと寿し 氷見本店 (ひみきときとずし) - 島尾/回転寿司 [食べログ]

夕飯

ブリしゃぶで有名なお店に行きました。食べログで雑に選んでます。

f:id:corocn:20171125172344j:plain

ひみ浜 (ひみはま) - 氷見/魚介料理・海鮮料理 [食べログ]

f:id:corocn:20171125172716j:plain

ブリ、ありました。 今回は1万〜1.3万円のコースです。値段は日によって変動するみたいです。

f:id:corocn:20171125173007j:plain

イワシ、バイ貝、イカの黒づくりなど

f:id:corocn:20171125173225j:plain

メインといっても過言ではないレベルの刺し身 この日のブリは11.3kgだったようです。

写真だと大きさが分かりにくいですが、巨大です。 そのへんの居酒屋の刺し身の5倍ぐらい。 左側が背中、右側がお腹だそうです。

f:id:corocn:20171125173648j:plain

塩焼きです。写真がドヘタクソですね。 油がすごいので、大根おろしには醤油をかけず、箸休めとしていただきます。

f:id:corocn:20171125173843j:plain

ぶり大根です。目玉まで、ほぼ全部食べてしまえます。 ブリしゃぶが控えているので、お腹いっぱいにならないよう気をつけて!と言われました。

鰤しゃぶ

本日のメインです。

これを!

f:id:corocn:20171125174152j:plain

これでしゃぶって!

f:id:corocn:20171125174235j:plain

こう!

f:id:corocn:20171125174248j:plain

うますぎる・・・

この後、氷見うどんとデザートのバニラアイスをいただきましたが、 お腹いっぱいで写真撮影を忘れました。

まとめ

氷見のブリは格が違う!

寒ブリのシーズンはこれからですが、美味しくいただけました。 ごちそうさまでした。

Google Home + Google Play Music 音声コマンドの日本語チートシート

ようやくGoogle Homeが日本でも発売されました。 私も買いました。

f:id:corocn:20171010214717j:plain:w400

Google Play Musicのユーザーなので連携をイイ感じにやってもらいたいのですが、 何て喋ったら良いのか分からないので、用途別のコマンドチートシートを作ってみました。

すべて「OK, Google」を先頭に発話します。

したいこと 発話 コメント
楽曲再生 音楽を再生 1曲だけ謎サジェストされる
曲名やプレイリスト名等から再生 <名称> を再生 カテゴリを一緒に言ったほうが認識しやすい
プレイリストを再生 <プレイリスト名>のプレイリストを再生 一番使ってる
アーティスト指定で再生 <アーティスト名>を再生
ラジオミックスを再生 <アーティスト名>のラジオを再生
ステーションを再生 <ステーション名>のステーションを再生 ステーション名なんて覚えられん
ジャンルを再生 - 再生に成功しない...
シャッフル (〜をランダム再生と発話)
ランダム再生を始める ランダム再生 次のトラックからシャッフル再生
止める 停止, 止める
再開する 再生, 再開する
次の曲 次の曲
曲をスキップ
シャッフルせず次へ
前の曲 前の曲
ミュート ミュート
音量を上げる 音量を上げる
音量を下げる 音量を下げる
音量を指定する 音量 <数字> 例: 音量 サン
再生中の曲名を聞く なんて曲? アーティスト名と曲名を教えてくれる
お気に入り 高評価, 高く評価

多分これ以上あると思うけど、日々使いそうなのはこんなところな気がします。 流し聞きすることが多いので、ステーションをもうちっといい感じに選択できるといいですね。(ステーション名なんて覚えれないし・・・)

間違いがあれば @corocn までご連絡くださいまし。

参考: 英語版 Plays incorrect song/playlist/artist/album - Google Home Help

Vue.jsのコードネームが面白い

こんにちは、@corocn です。

Nagoya.js #3もくもく会で、Vue.jsのコードネームが面白いという話で盛り上がってました。

日本のマンガやアニメにちなんだ名前が採用されています。

version code name original
2.5 Level E レベルE
2.4 Kill la Kill キルラキル
2.3 JoJo's Bizarre Adventure ジョジョの奇妙な冒険
2.2 Initial D 頭文字D
2.1 Hunter X Hunter Hunter x Hunter
2.0 Ghost in the Shell 攻殻機動隊
1.0 Evangelion エヴァ
0.12 Dragon Ball ドラゴンボール
0.11 Cowboy Bebop カウボーイビバップ
0.10 Blade Runner ブレードランナー
0.9 Animatrix THE ANIMATRIX

※間違いがあるかも

以下にもまとまっていますね。

https://github.com/egoist/always-bet-on-vue

v2.4はここで予想されているみたい。 アルファベット順なので次は「K」が採用されますが、キルラキルにbetが集まってますね。

f:id:corocn:20170603213111p:plain

個人的に、かずぽん氏がカイジ推しで面白かった。