みずぴー日記

人間の再起動ボタンはハワイのビーチにある

💻デスクトップマスコット

f:id:mzp:20180620232647p:plain

美少女として勤務するで作ったアバター表示アプリと、デレステフォトスタジオのリアルタイム透過プレイヤーをつくったのクロマキーフィルターつきiPhoneキャプチャを組合せることでデスクトップマスコットになった。

👚ポーズ

デスクトップマスコットになるには全身を写す必要があるので、Tスタンスではなくかわいいポーズが必要となる。

いろいろ見た中で、以下のポーズのうちミクの後ろに腕をまわしているポーズがかわいかったので採用した。

seiga.nicovideo.jp

そのまま適用するとこうなる。

f:id:mzp:20180620233126p:plain

とてもかわいいが、上半身と首をひねっているため長時間は厳しい。 多少、ポーズは修正した。修正はVmd2XMLを利用した。

f:id:mzp:20180620233935p:plain

かわいいには我慢がつきものらしい。

🏟背景色

クロマキー合成をするために背景を単色に切り替えれるようにした。 これはカメラのSkybox設定をいじって実現した。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeBackground : MonoBehaviour {
    private int count = 0;

    public void OnClick() {
        count = (count + 1) % 4;

        switch(count) {
            case 0:
                Camera.main.clearFlags = CameraClearFlags.Skybox;
                Camera.main.backgroundColor = new Color(49/255.0f, 77/255.0f, 121/255.0f);
                break;
            case 1:
                Camera.main.clearFlags = CameraClearFlags.SolidColor;
                Camera.main.backgroundColor = new Color(0.15f, 0.48f, 1);
                break;
            case 2:
                Camera.main.clearFlags = CameraClearFlags.SolidColor;
                Camera.main.backgroundColor = new Color(1, 3/255.0f, 102/255.0f);
                break;
            case 3:
                Camera.main.clearFlags = CameraClearFlags.SolidColor;
                Camera.main.backgroundColor = new Color(251/255.0f, 179/255.0f, 2/255.0f);
                break;
            default:
                break;
        }
    }
}

そのままMastodonでtootしたらコマ割りされたみたいになってよかった。アニメのアイキャッチ画像っぽい。

f:id:mzp:20180630154431p:plain

📷カメラ位置の調整

全身がはいるようにカメラ位置をずらした。 こうしてみると、引きで写すとかわいい衣装がよく見えて、いいのかもしれない。

f:id:mzp:20180620234751p:plain

その他

💎RubyKaigi 2018

RubyKaigi 2018に参加した。 RubyKaigi(仙台)、WWDC(サンノゼ)、出張(東京)というかなり強い日程になっていたがなんとか落ち着いた。

f:id:mzp:20180530121726j:plain

🎤セッション

Rubyの型に興味があったので、型の話を中心に聞いた。

ASTのまわりの発表がいくつかあったので聞いた。 やっぱり型と文法には興味ひかれる。

TRICK 2018 (FINAL)は見たかったが移動と被ってしまって見られなかった。 残念。

✨ブース

開始直後にEightのTシャツを貰いにいったら写真を撮られた。美少女として勤務するで笑顔の練習をしたので、なんとか笑えた。

定期的にコーヒーが提供されててうれしかった。

f:id:mzp:20180531123956j:plain

お弁当おいしい。 牛タンを食べにいくタイミングがなかったが、お弁当で食べれた。

f:id:mzp:20180531120035j:plain

⌨️SKK

SKKこと仙台高等工業学校の跡地も見にいった。

f:id:mzp:20180530141855j:plain

日本語入力のSKKとの関係は微妙で、関係は明言されていないが無関係のはずがないくらいの感じになっている。Wikipediaでは以下のように断言を避けている。

また、東北大学の教授により開発されていたわけであるが、新制東北大学の工学部の母体のひとつ仙台高等工業学校の略称もSKKである。

SKK - Wikipedia

それはそれとして、校歌が刻まれた石碑があってよかった。

f:id:mzp:20180530142550j:plain

校歌だけあって、言葉が格調高くていい。「SKKのわかき子」「SKKの名を揚げよ」が心に染みる。

f:id:mzp:20180530142702j:plain

f:id:mzp:20180530142656j:plain

f:id:mzp:20180530142708j:plain

そのあと年表を見たら「SKKの名は消えた」と書いてあって、アッとなった。

f:id:mzp:20180530142757j:plain

🦀瑞鳳

瑞鳳のバイキングがやばいと聞いていたのでRubyKaigiの前日に泊まった。

togetter.com

同僚2人と泊まったが部屋が異様にひろくてびびる。

f:id:mzp:20180530171157j:plain

部屋の玄関が広すぎる。

f:id:mzp:20180530171137j:plain

聞いていたとおり夕食が豪華。好きなだけ蟹が食べれる。

f:id:mzp:20180530192411j:plain

肉もある。

f:id:mzp:20180530192442j:plain

温泉も広くて最高だった。

🍽食事

移動に追われたせいで街中で買い食いしたくらいしか仙台っぽいものを食べていない。

仙台にしかないという土鍋チーズこってりの天下一品。

f:id:mzp:20180530131756j:plain

ひょうたん揚げ。 かまぼこで作ったアメリカンドッグみたいな味がする。

f:id:mzp:20180530133853j:plain

たいやき。

f:id:mzp:20180530150412j:plain

⏰時短勤務

勤務時間を7時間/日とする時短勤務をはじめて1年半ほどが経過した。

かなりよいのでまとめておく。 年収の向上と同程度の価値があると感じている。

f:id:mzp:20180530215053p:plain

🏢業務

業務内容は大きな変化なく、支障なくできている(と思う)。 いくつかの要因がありそうだが、よく分からない。

  • 8時間勤務のうち最後の1時間は疲労していることが多い。疲労していて生産性が悪い時間がなくなっているだけなので、影響は少ない。
  • フレックス勤務なのでまとめて働きたい日は残業して、他の日に早く帰るなどの調整をしている。
  • もともと全員の出勤時間・退勤時間はばらばらなので、自分が早く帰っても周囲の負荷が少ない。

🍻ハッピーアワー

たまたま無職・休職中の知り合いが多かったのでハッピーアワーに飲みに行っていた。なぜか寿司の写真が多い。

f:id:mzp:20180129183425j:plain

f:id:mzp:20170601201940j:plain

f:id:mzp:20180321194532j:plain

大半が職を得てしまったので今後は難しいかもしれない。大半の友人はフルタイムで勤務しているので、ご飯の約束をすると、どこかで時間を潰す必要が生じる。

🚶‍♂️通勤

自由になる時間が増えたので、これまで電車で移動していた区間を徒歩にするなどしてゆっくり通勤するようにした。

最初のうちは新鮮でよかったが、だんだん飽きてきた。 それでも気分転換になるので、たまにやっている。

通勤途中にある神社がひょうたん推しでおもしろかった。

f:id:mzp:20180530215014p:plain

♨️スーパー銭湯

時間に余裕ができたので、スーパー銭湯にたまに行くようになった。

気分転換と疲労回復を狙っているが、継続的に成果を出し続けるたったひとつの冴えたやりかた - Misoca開発者ブログにあるように温泉の近くに住んだほうが効率がよい気がする。

👜リモートワーク

旅先でリモートワークをし、仕事後に観光するのを何度かやった。 これは時短勤務ととても相性がよい。

旭川の街中を散歩しているときの様子。

f:id:mzp:20170612180456j:plain

松江の宍道湖から見た夕日はよかった。仕事終わりが日没ぎりぎりになってしまったので、あわてて走った。

f:id:mzp:20180208084312j:plain

雪がやばいということに目をつむれば、玉造温泉はすごく雰囲気がよかった。

f:id:mzp:20180208233742j:plain

✨個人活動

技術書典参加などは、自由になる時間が増えたおかげである。

執筆の負荷がだいぶ軽減されたと思う。いきなり2冊出せたのも執筆時間が確保できたのが大きい。

f:id:mzp:20180422102943j:plain

🎬映画を見る

会社帰りに映画を見にいきやすくなるかと思ったが、これはうまく行かなかった。

これは「開始時間が固定なので早く仕事が終わっても早く見れるわけではない」「そんなに映画が好きではない」などの理由が大きい。結局、家でNetflixを見ている。

💖美少女として勤務する

パペ文字によるVR出社 を継続している。 楽しい。

f:id:mzp:20180516212627j:plain

🌟アバターの変更

パペ文字に搭載されているモデル以外の美少女にもなりたくなったので、Unityでアバター表示アプリを作成した。

モデルは物述有栖を利用している。 かわいいのと、ライセンスが明確なのがよい。

f:id:mzp:20180516212722j:plain

実装は以下のページが参考になった。

📸自撮りボタンの追加

Unity+iOSでカメラロールにスクショを保存するまで - Qiitaを使って、スクリーンショットを手軽に撮れるようにした。

f:id:mzp:20180516214118p:plain:w300

カメラロールがどんどんかわいくなっていく。

f:id:mzp:20180516214418p:plain

🛠ライトニングドック

常に顔を映せるようにライトニングドックを購入した。 便利なの自宅用とオフィス用を買った。

f:id:mzp:20180516124820j:plain

iPhoneが常に起動しつづけることになるので、だいぶ発熱する。

☺️表情

夕方になると表情が死んでくることを発見した。目が閉じ気味になって、口が開き気味になる。かわいさが半減してしまうので、積極的にほほえむように気をつけはじめた。

f:id:mzp:20180516215553p:plain:w300

でもあくびしててもかわいい。

f:id:mzp:20180516215839p:plain:w300

🙊周囲の様子

mstdn.jp

mstdn.jp

mstdn.jp

🙅‍♀️zoom.us への接続の改良(失敗)

デレステフォトスタジオのリアルタイム透過プレイヤーをつくった - ツバメになったバリスタを応用して、zoom.us への接続を改良しようとしたが

Zoom APIを用いて、iPhone画面を直接配信できるようにしようとしたが、変更できる範囲が少なくどうしようもなかった。

☕️ JavaScriptと入力メソッド

AquaSKK 4.5.0ではEscキーの扱いを改善した。 この修正のためにWebKitにおけるキーイベント配信の仕組みを追ったので、まとめる。

💡入力メソッドごとの差異

上記Tweetにあるように、テキストを入力中にEscを押した際にJavaScriptで発火するイベントが入力メソッドごとに違う。

macOS標準の日本語入力やGoogle日本語入力ではキーコードが229のイベントが発生するが、AquaSKKではキーコードが27のイベントが発生していた。 このイベントが違うと入力メソッドを扱うJavaScriptコードが複雑化するので修正した。

🔑キーコード 229

キーコード229はUI Eventsで次のように定義されている。

If an Input Method Editor is processing key input and the event is keydown, return 229.

(訳: 入力メソッドがキー入力を処理しておりイベントが keydown の場合は、キーコードは229となる)

🌐WebKit

W3Cが定めているキーコードなのでブラウザ内部の処理が関係するのだろうと想定して、WebKitのコードを調べた。

WebKitはアプリケーションのUIを実現するUIプロセスとタブごとに作られるWebプロセスが協調して動作している。 キー入力の処理もこの2つのプロセスが関連している。

f:id:mzp:20180514223203p:plain

UIプロセス

// Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm

void WebViewImpl::keyDown(NSEvent *event)
{
    // (snip)

    // 入力メソッドに処理を転送する
    interpretKeyEvent(event, [weakThis = createWeakPtr(), capturedEvent = retainPtr(event)](BOOL handledByInputMethod, const Vector<WebCore::KeypressCommand>& commands) {
        ASSERT(!handledByInputMethod || commands.isEmpty());

        // キーイベントに入力メソッドが処理したかどうか(handledByInputMethod)を付与して、Webプロセスに転送する
        if (weakThis)
            weakThis->m_page->handleKeyboardEvent(NativeWebKeyboardEvent(capturedEvent.get(), handledByInputMethod, weakThis->m_isTextInsertionReplacingSoftSpace, commands));
    });
}

void WebViewImpl::interpretKeyEvent(NSEvent *event, void(^completionHandler)(BOOL handled, const Vector<WebCore::KeypressCommand>& commands))
{
    // (snip)

    // Cocoaが提供するAPIを使ってイベントを入力メソッドに転送する
    [inputContext() handleEventByInputMethod:event completionHandler:[weakThis = createWeakPtr(), capturedEvent = retainPtr(event), capturedBlock = makeBlockPtr(completionHandler)](BOOL handled) {
        if (!weakThis) {
            capturedBlock(NO, { });
            return;
        }

        LOG(TextInput, "... handleEventByInputMethod%s handled", handled ? "" : " not");
        if (handled) {
            capturedBlock(YES, { });
            return;
        }

        auto commands = weakThis->collectKeyboardLayoutCommandsForEvent(capturedEvent.get());
        capturedBlock(NO, commands);
    }];
}

入力メソッドにキー入力を転送するのに非公開のAPIを利用している。愉快。公開されているAPIと違い、処理結果をコールバックで受けとれるようになっている。

// FIXME: Move to an SPI header.
@interface NSTextInputContext (WKNSTextInputContextDetails)
- (void)handleEvent:(NSEvent *)event completionHandler:(void(^)(BOOL handled))completionHandler;
- (void)handleEventByInputMethod:(NSEvent *)event completionHandler:(void(^)(BOOL handled))completionHandler;
- (BOOL)handleEventByKeyboardLayout:(NSEvent *)event;
@end

Webプロセス

WebプロセスではUIプロセスで付けられたマークをもとに、元のキーイベントを配信するかキーコード229のイベントを配信するかを決めている。

// Soruce/WebCore/page/EventHandler.cpp

// Match key code of composition keydown event on windows.
// IE sends VK_PROCESSKEY which has value 229;
const int CompositionEventKeyCode = 229;


bool EventHandler::internalKeyEvent(const PlatformKeyboardEvent& initialKeyEvent)
{
    // (snip)
    
    // キー入力が入力メソッドで処理ずみかどうかを判定する
    bool handledByInputMethod = keydown->defaultHandled();
    
    if (handledByInputMethod) {     
        // 入力メソッドで処理済みだったらキーコードを229に入れ替える
        keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
        keydown = KeyboardEvent::create(keyDownEvent, &m_frame.windowProxy());
        keydown->setTarget(element);
        keydown->setDefaultHandled();
    }

    // (snip)
    // キーイベントを配信する
    element->dispatchEvent(keydown);

    if (handledByInputMethod)
        return true;

    // 入力メソッドで処理されていないなら処理を継続する
    // (snip)
}

🙊余談

  • JSに配信されるイベントを見るにはKeyboard Event Viewerが便利。
  • WebKitを処理を追うときはXcodeでブレイクポイントを設定して追った。 Debugging WebKitが参考になる。
  • WebKitのビルドに時間がかかってつらかったので、途中で会社のiMacProに接続してビルドしはじめた。 あとからビルドを始めたのに、先にビルドが終わったのでびびった。

🌕月を売った男

人月の神話では、理想のチーム形態として、R.A.ハインライン月を売った男の文章が引用されている。

引用されている文章(要約)

プロジェクトのリーダーが雑務に追われることを嘆くところから引用ははじまる。

コスターは両手で顔をおおってしまったが、やがて顔を上げる。「わかってます。なんとかしなければいけないとわかっているんです --- しかし、わたしが何か技術的な問題と取り組んでいると、阿呆なとんちきがやれ輸送の問題だ、やれ電話だなんだかんだと、つまらんことでわたしに決定を求めてくるんです。 すみません、ハリマンさん。自分ではやれると思っていたんですが」

出資者がその事態を改善するために業務を調整する。

ハリマンはうんとやさしくいった。 「(略) わたしが4、5日そのデスクにがんばって、きみがそんなつまらんことから守ってもらえるような体制をととのえよう。 わたしが求めているきみの頭脳は、反動ベクトルとか燃料効率、設計荷重などということを考える頭脳で運送契約なんかを考える頭じゃないからな」

さらに今後の業務を調整するアシスタントもつける。

「ボブ、ジョック・バークリュウイーを紹介しよう。彼はいま、きみの奴隷だ。 きみは主任技師で最高のだれにも制約されない責任者のままだよ。 ジョックはいわば、ほかの仕事を引き受ける摂政殿下だな。 これから、きみは全然何にもわずらわされることはないよ --- ただ、月ロケットを作る細部の問題は別だがね」

おもしろい点

たしかに理想的なチームのように思える。 この「月を売った男」は1950年でた小説なので、60年以上前に描写されたチームが理想的に思えるのはおもしろい。

さらにおもしろいことに「月を売った男」は絶版しているが、人月の神話は新装版が入手可能である。 引用の中に生きつづけるSF小説、ロマンがあってよい。

手元にある「月を売った男」と「人月の神話」

引用されている文章がよかったのでAmazonマーケットプレイスで購入した本。

f:id:mzp:20180510224310j:plain

「いまだ色あせない」と書こうかと思ったが、本はだいぶ変色していた。「近ごろは、技術的な仕事もあまりできてないな?」「やろうとはしているんです」のやりとりもだいぶいい。

f:id:mzp:20180510224433j:plain

✏️#技術書典 に本を出すまで

技術書典4で頒布した同人誌ができるまでの流れを記録する。

✨書きはじめたきっかけ

@が技術書典3に出展してて楽しそうだったので、自分もやってみたくなった。

前々から入力メソッドの作り方を調べ直そうと思ってたので、それを題材に選んだ。 AquaSKKをメンテナンスに必要な部分は知っているが、Swiftから使うとどうなるかなどは未知の部分なのでそこを埋めたかった。

ただ調べるにつれて、ほぼ資料がないことが分かってきたので、すこしでも資料を増やすためにこの本を出さなければならない、という使命感で書いていた。

📚本のスタンス

「資料を増やしたい」というのが目的にはいっているので、同人誌を読まないと得られない情報というのを極力減らしたかった。

なので、このブログに同等の内容を載せるようにした。 入力メソッドで検索すると同人誌と同等の内容が書いてある。だいたい1エントリが1章に対応するはずだが、構成の都合で変更した部分もある。

f:id:mzp:20180425072321p:plain

多くの人にはなじみがない分野だろうと思ったので、イラストを多めにしたかった。

かわいい女の子のイラストにしたかったが、すべてイラストレーターさんにお願いする予算はないのであきらめた。かわり謎の生命体を自分で描いた。

f:id:mzp:20180425072134p:plain

📅本ができるまで

調査開始

🍣入力メソッドが最初に調べたことなので、技術書典3の直後くらいから調べはじめていた。 RubyKaigi 2017に移動する新幹線の中で調べていた記憶がある。

このころはScrivenerに調べた結果を書き溜めている。このころは本文中に絵文字を使っているが、組版でこれがネックになる。

f:id:mzp:20180425072749p:plain

執筆開始

技術書典にサークル申し込みしたあとからRe:VIEWで書き始めた。落選したときのことはあんまり考えてなかった。

f:id:mzp:20180425073337p:plain

レポジトリは、ちょうどローンチされた直後のKeybaseの暗号化gitを利用した。 GitHubでない強い理由はないが、新しいものを使ってみたかった。

推敲

1月末に当選したことが分かったので、本格的に推敲しはじめた。最初はPDFとiPadでやっていたが、文字サイズが妥当かどうかわからなくなったので、紙とペンに切り替えた。

f:id:mzp:20180424215928j:plain

印刷して推敲するの、結局4回ほど繰り返した。

f:id:mzp:20180424215915j:plain

途中、温泉で推敲するという文豪ごっこをやったが、温泉に入るだけで終わった。

f:id:mzp:20180211164843p:plain

イラスト・図

できるかぎりイラスト・図を増やしたかったのでProcreateで描いた。

f:id:mzp:20180425075231p:plain

文字はApple Pencilを使ってもうまく書けなかったので、Sketchを使って入れた。

f:id:mzp:20180425075533p:plain

書体の変更

たまたま入った本屋でデザインのひきだしのバックナンバーを大量に手にいれてしまった。

これでブックデザインに凝りたい気持ちが高まってしまって困った。 とりあえずAdobe Typekitに加入して見出しや本文の書体を変えた。

見出しはかわいらしさをだすために視覚デザイン研究所のメガ丸にした。 本文書体は、一〇〇年目の書体づくりを読んで以来ファンなので、秀英明朝にした。

f:id:mzp:20180425074658p:plain

この書体変更のためにRe:VIEWが使うTeXエンジンをLuaLaTeXにいれかえた。 わりと大変だった。

入稿

栄光が同人の日キャンペーンで30%オフをしていたので、これを利用した。

f:id:mzp:20180425075748p:plain

だいぶ余裕をもって書き上げたはずだが、入稿するときにPDFをアプロードし忘れるなど、だいぶスリリングだった。

2冊目

3月末ぐらいで書くものがなくなって暇になった。 サークルスペースにも余裕あるしな、と思って2冊目を書きはじめた。 この話は工場実習日記 ふりかえりに書いた。

当時のことをがっとノートに書いてから書きはじめたので、すごい雑な図が手元にある。

f:id:mzp:20180424230107j:plain

完成

どきどきしながら技術書典の会場にいったら届いてて安心した。 よかった。