あーあーそのー

最近はshuyuheyと名乗ることが多いですが面倒なのでBLThunder1991のままにします。

別に公開とかはしないんだけどゲームのプレイ動画を録画したりしている

Among Usというゲームを月に2回ぐらいのペースでやっている。友達とか友達の友達*1とかがゆるくあつまっているDiscordを作っていて、だいたい20人ぐらいになった。みんなそれぞれ忙しかったりモチベーションに差があったりで、毎回なんとか10人ぐらい集めるけど1人か2人は初めて参加する人がいるような感じ*2

その会でプレイするときは、自分のプレイ動画とDiscordの会話を録画するようにしている。使っているツールはOBS。

obsproject.com

配信者になって一発当ててやろう的なモチベーションではなく、旅行に行ったときのホームビデオ的な感覚で録画してあとからなにかのネタになればいいな、ぐらいの気持ちでやっている。

実際見てみると「このときこれを見逃してたから負けたんだなー」とか、「ここでこう言っておけば吊られなかったかもな」とか考えるきっかけになるし、見てくれた人からは「(自分では白いと思っていたけど)shuyuhey視点だと自分は怪しかったんだな」みたいなコメントをもらったりする。

見返してみると色々発見があったり、(たぶん)うまくなるための近道になったりするので環境を作れる人は録画にチャレンジしてみるとよいかもしれない。

ここからは現在の環境とか設定とかやっていることなどを忘れないように書いてみる。

僕の環境は、次のような感じなので、そのまま設定をするとなんかうまくいかないこともあるかもしれないがご了承ください。

*1:もはやもう友達なのかも

*2:気合いを入れればもっとバンバン僕の友達を突っ込めるのだけど、僕ばっか人を連れてきてもなあとか思ってそれなりにセーブしている

続きを読む

Among Usを快適にプレイするために、Discordのボイスチャットを一括でミュートしたりミュート解除するツールを書いている

はじめに

最近、休みの日の夜に友人たちとAmong Usというゲームをプレイしています。 やったことがある、あるいはYouTubeなどで見たことがあるという方もいるかと思います。

簡単に説明すると宇宙船の船員の中に船員を殺害する裏切り者の「インポスター」がいて、船員はインポスターを会議であぶり出して追放しつつ宇宙船の修理タスクの完了を目指す、というゲームです。船員の中に潜むインポスターを会議であぶり出す、という特徴から宇宙人狼と呼ばれることもあります。

このゲームでは、死体を発見したときとステージのどこかにある緊急招集ボタンを押したときに全員参加の会議が開かれます。ゲーム内でもテキストチャットが用意されていますが、実際はDiscordなどのボイスチャットを使うことが多いと思います。会議以外はミュートしてタスクをすすめ、会議のときだけミュートを解除する。ただし、インポスターに殺されたあるいは追放された船員は会議中であってもミュートをする、という独自ルールでプレイしていることが多いのではないかと思います。

このミュートにかんして、色々思うところがあってツールを書くことにしました。

公開できるぐらいにはまとめましたが、今後も継続して開発するかどうかは決めていないので、ある程度自分で面倒を見れそうな方は使ってみていただければ、と思います。

続きを読む

2020年振り返り

毎年色々あるのだけど、2020年は書き残しておきたいことがいくつかあるなあと思ったので振り返りを書いてみることにします。

気づいたら今年も1ヶ月が過ぎようとしていて困りますね。

仕事

workhopリリース

workhopというサービスのリリースに一貫して関わりました。現在は株式会社nというところにいるのですが、2019年の5月に入社してからいろいろな会社の業務委託を受けたり、プロダクトのプロトタイプを作りながらようやくリリースにこぎつけました。

細かいところは割愛しますが、おかげさまで順調にサービスは成長しております。サービスを作って育てていくことは好きなので、それを会社創立の一期目で達成できたのはうれしいし、自分にとっても自信になりました。

このサービスはGKEの上で動いており、バックエンドにRails、フロントエンドにNext.jsを採用しています。2021年はこのあたりのこともブログに書いたりできると良いなあ。

enPiT2

2019年に引き続きenPiT2の夏合宿にメンターとして参加しました。TDDワイワイ会を一緒にやったり、合宿中に作っていたプロダクトにフィードバックをしたりするのが仕事でした。

2019年と違うところは全編オンラインでの開催だったことです。

これまでは御殿場にいったり箱根に行ったり、オフラインということでメンターとしてだけではなく授業以外の時間もたくさん関わることができたのですが、今年はそうはいかなかったので最後まで学生のみなさんの顔と名前が一致しなかったのは残念なところでした。

オンラインでのフィードバックは、表情が見えないのでうまく伝えられているか最後までわからなくて、難しいなあと思いました。表情や雰囲気に頼らず、良いフィードバックができるよう訓練が必要だなと思いました。

プライベート

個人的な目標

前職の後半あたりから、書いてあることをそのまま受け取る練習が必要だなーと思っていて、その流れの先にある目標です。

性格上、書いてあること以上のことを読み取ろうとして辛い気持ちになったり勝手に怒ったりすることが当時よくあって、そういうのはあまり意味がないし疲れるだけなのでやめよう、というやつです。

今年は、それを書いてあることだけじゃなくてちょっとした仕草や表情、振る舞いとかからも邪推しようとしてしまうところを控えたいなぁと思っています。

家庭

子どもがうまれました。

前職では子育てメディアの開発をしていたので、それなりの知識があってアドバンテージがあるぞと息巻いていたのですが、そうでもなかったです。

インターネット上にある様々な知識は役に立つこともあれば、全然役に立たないこともある、ただただ目の前にいる子どもと向き合って一つ一つ試していくしかねぇんだよな。

子どもがうまれたことで、今までできていたことが出来なくなることを少し心配していたのですが、飲みに行こうにもどうせこのご時世は無理だし、趣味でコードを書こうと思えばまとまった時間は無理でも工夫すればなんとかなることがわかってきたので、今のところ乗り切れそうです。

夫婦2人で過ごす時間はなくなってしまったので、それだけ少し気にしています。まあ3人で別の楽しみ方をするだけなのかな、とも思いますけど。

おわりに

公私ともに仲良くしていただいている皆様、引き続き今年もよろしくお願い申し上げます!

Agile PBL祭りに参加してきました

行ってきました。

色々と環境が変わって、チーム開発みたいなものから少し離れていたので、やや不安があったりもした*1のですが参加しました。

agilepbl.connpass.com

Agile PBL祭りって何?という方は以下のエントリに運営メンバーのみなさまによる思いが書かれておりますので、ぜひ読んでみてください。

miholovesq.hatenablog.com

note.com

今回はコミュニティスポンサーという枠があり、微力ながらTDDワイワイ会もスポンサーさせていただきました。

TDDワイワイ会ステッカーが貰えるのはTDDワイワイ会だけ!というわけでTDDワイワイ会もぜひよろしくおねがいします。

tddyyx.connpass.com

当日の雰囲気

Twitterハッシュタグ#agilepbl )を追いかけていただくと、当日の雰囲気をなんとなくつかむことができると思います。

口頭発表とデモ

口頭発表→デモ展示の順番を、お昼を挟んで3回繰り返しました。

口頭発表では特にフォーマットもなく、皆さんが自由にデモへの取っ掛かりを作っていた印象を受けました。 デモのときに「あのときこう言ってたと思うんですけど〜」という感じで話しかけに行きやすくて良かったと思っています。

「POの我が強くて大変だったんだけど、結局はそれが良かったんだと思う」みたいな話とか「チームの技術力が低かったので、とりあえず手を動かす組としっかり基礎を学ぶ組に分かれてやってみました」みたいな話があり、チームで開発していく中での気付きだとか、自分たちの状態を把握した上での工夫だとか、各チームの試行錯誤の歴史に触れられてよかったです。

多くの場合、チーム内に最初のユーザがいて(多くの場合はその人がPOをしていそう)、メンバーの誰に聞いてもだいたいの機能とかデザインの理由について説明できるのがすごかったです。 最初から作っていると言うのもあるし、プロダクトの規模が比較的小さいのもあるけど、プロダクトについてみんなが全部わかっている状態って改めて良いなーと思いました。真似していきたい。

なによりデモでは皆さん楽しそうにしていたのが印象的でした。帰りに「あっ、こういうことも聞けばよかったなあ」ということを思いついたので次の機会にはぜひ聞いてみたい。

ワイワイスポット

会場には雑談スペースみたいなものも用意されていて、学生や参加した社会人ごちゃまぜで色々と議論できたのも面白かったです。社会人同士で色々話しているところに学生が混ざってきたりとか。

地元のお祭って露天でなんか買うのもいいけど、久しぶりにあった友達と端っこの方でしゃべるとか、運営よりの大人たちと喋るとか、そういうのが楽しいこともあるじゃないですか。 偶然なのか狙ってるのかそういう雰囲気を感じられて面白かったです。

自分の学生時代を振り返ると

今回のAgle PBL祭りとは開催目的がやや異なりますが、僕も学生時代にPBL Summitというイベントに参加したり、運営をしていたりしました。

全国からPBLをやっている学生を集めて交流する、というのが主たる目的のイベントで、当時の参加大学で今回のAgile PBL祭りに参加している大学もちらほらあります*2。残念ながら現在まで続いているイベントではないですが*3、こういうイベントは続けることそのものがとても難しいなあと思っているので、僕自身も参加された皆様もどんな形でもいいのでこの取組を応援できると良いですよね。

このイベントに関わっていた当時から思っていたのですが、自分たちがやったことを題材に人と話すのって本当に楽しいし学びになるんですよね。一生のうちに自分が所属できるチーム数なんてたかが知れているので、こういう場でいろんなチームのやり方とか考え方を吸収するのって意義があることだと思います。今回は僕がたくさん学びをもらってしまった感じがあるので、次回までにもう少しいい感じのおとなになるぞ。

*1:僕が提供できるものがあるのだろうか、的な意

*2:それだけ長いことPBLをやっている大学があるんですよ〜

*3:ここまで続いていないのは僕にも責任の一端があり、心苦しい

ISUCON8予選に参加しました

ISUCON8に参加しました。参加は今年で3年連続3回目です。

ちなみに体調は最悪で、風邪を引いていたのもあり声がほとんど出ませんでした。チームメンバーの皆様にはご迷惑をかけてしまった。

isucon.net

結果は今年も予選落ちでした。うーん残念。着実に良くなっている感じはあるものの、次こそは予選突破したいなあ。

メンバー

実は毎年参加するチームが変わっています。今年は、Takuan-Oishiiさんと、hommahさんとのチームでした。

会社の同僚と、高専の同期というやや異色なチームでしたが、共通の知り合いである僕の心配をよそに、持ち前のコミュ力で普通に打ち解けてました。すげえな。

事前準備

キックオフの飲み会も含めて、合計3回ほど集まって練習しました。

基本はisucon7の感想戦を題材に、「どういう手順で何を調べたら我々はこのボトルネックに気づいて対処できたか」みたいなことを中心に考えました。なので、「ここまでこうやって設定している間に、誰がどういう風にレギュレーション理解しているといいのかな」とか「こういう手順でログを見たら、例えばここがおかしそうっていうことに気がつけるんじゃないかな」とか当日でも行動が再現できるレベルになるようにいろいろ考えられたことはすごく良かったように思いました。まあ予選落ちしたんだけど。

個人的には「当日の我々の知能レベルでは〜」のようなチーム内に独自の語彙というか言い回しが発生したのが面白かったです。よくあることだと思うんですが、チーム内に独自の共通言語が生まれるって、チームとしては割といい兆候な感じしませんか?しますよね?

事前練習までは、 1. 誰かがSSH鍵を配置して初期の設定完了させましょう 2. その間に残りの2人がレギュレーションとアプリをみてどんなものかを理解しましょう 3. その後、最初に手を付けるべきボトルネック2つぐらい出したら早速それに取り掛かることにしましょう

という感じのことを決めました。

あとは各々、手元のスクリプトをメンテしたり、僕はすばやく環境流し込んだり設定変更できるようにansibleのスクリプトを書いたりしていました。

当日

基本的には自分がやったこととか、関わったことしか覚えてないのでそれぐらいしか書きません。

当日は、事前準備で話していた1,2,3がそれぞれうまく実行できて、順調な滑り出しに見えました。

ただ、nginxしか頭になかった状態でのまさかのh2oで、どぎまぎしながらも設定ファイルをいろいろ変えてalpが使えるように変更した上で改善に取り組みました。alpに結構頼るつもりだったので、肝が冷えました。

終了後の感想チャットで「すぐnginxに変えた」っていうのを見て、確かにその手もあったなって思いましたw意外と焦っているもんだ。

最初は結構無駄なクエリ多いね、っていう話になってクエリを削る方向に行くかと思いきや、インデックス効いてないところを細々直したりしてました。今振り返るとあんまり筋がいいことしてないなあ。あとは、最初は1台構成だったものを2台に変えたり。

そんな感じで、今思えばほそぼそとした改善しかしておらず、初期スコアから全然変わらず。

最後の最後に、イベント取得のクエリがループ使っていて激重だったので、いい感じにチューニングしたら最後に1万ぐらいいきました。その時のチューニング結果のコミットというか動作確認の手順をミスって、泣きの1回ベンチの機会を失ってしまったのは素直に申し訳ないという気持ちでいっぱい。

あと、ちょくちょくペアで作業したりできていたのは個人的には楽しかったなあ。完全分業っていうのもISUCON的には戦略としてありだと思うけど、個人的にはワイワイやるのがやっぱり好きです。

感想

相変わらずISUCONはおもしれえなあっていう気持ちでいっぱいです。終わるたびに「はぁ〜」ってなるんですけど。

事前に色々考えたとしても、やっぱり当日は一歩及ばないっていうのを何度も繰り返している気がしていて、エンジニアとしてもまだまだだなあと思います。精進が必要だ。

あと、過去参加した中で一番ポータルサイトがリッチで声が出ました。嘘です。当日僕が声出ませんでした。でもびっくりしたのは本当です。 あんなに大変なイベントの運営をしてくださっているスタッフのみなさま、本当にありがとうございました。来年こそは予選を突破したい!

XP祭りに参加してきてTDDワイワイ会をやってきました

最近、何かしらのイベントに参加したらブログを書いたほうがいいのではないか?と思い始めたので、思いが続く限り書いてみようと思います。


TDDワイワイ会

XP祭り2018に参加してきました。初参加ながらTDDワイワイ会の出張ワークショップをしてきました。

tddyyx.connpass.com

基調講演がt_wadaさんの「テスト駆動開発の過去・現在・未来」だったというのもあり、これは割と人が来てくれるのでは?と期待しましたが、やっぱりたくさん来てくれて、ありがとうございました。プロジェクターを持ち寄ったかいがありました。

当日は僕がインストラクションを担当して、TDDとかモブプロの説明をしました。普段と変えたのは、最初に全体に対してTDDの説明をしたことと、1セッションで終わったこと。当日は「筋トレです!」っていうのを何度か言ったからか、参加者の皆さんは最初から筋トレスタンスで臨んでいたように思いました。次からも筋トレ筋トレ連呼しよう。

なんだかんだいつもと違うことが多かったからか、終始緊張をしていたような気がします。あんまり上手に振る舞えなかったなあとちょっとだけ反省しています。あと、普段から運営メンバーには説明がぶっきらぼーと言われることが多いのですが、今回も例にもれずぶっきらぼーだったみたいです。だんだんとぶっきらぼーにならないように改善します。次はうまくやるぞ!

あの場で少しでも面白いな〜と思ってくださった方がいれば、ぜひいつものワイワイ会にも参加してくれるととても嬉しいです。次回は、沖縄と東京での開催が決まっています。

tddyyx.connpass.com

tddyyx.connpass.com

全体の感想

実はワイワイ会で疲れてしまったからか(あとワイワイ会ちょっと長かったし)他のセッションをたくさん見れたわけじゃなかったので、来年参加することがあればもうちょっと余裕を持って振る舞いたいなあと思います。最後のLTはLTだな〜〜っていう感じで本当に面白かったです。語彙力がない。

懇親会では目ざとくスクリーンを見つけ、ワイワイを始めてしまいました。なんでかわからないけどたまたまプロジェクターを持ち歩いていたもので。本当に何から何まで楽しかったです。

スタッフの皆様お疲れ様でした、そしてありがとうございました!

Riot.jsでどんどん重なっていくモーダルの背景色を薄いまま保つ

最近Riot.jsを使った案件をやっていて、そこで困ったことをどう解決したかを整理しておく。

やりたかったこと

Webの表現ではよくあると思うのだけど、要素をクリックすると詳細な画面とかメッセージがポップアップっぽく表示されて、後ろが半透明の黒背景で覆われていて他の要素がクリックできないようになる、みたいな要件。

f:id:BLThunder1991:20180722123557p:plain

今回の要件では、モーダルの中で再び別の要素をクリックすると、それが更に重なってモーダルで表示されるというものになっていた。モーダルがどんどん重なっていく、ということ。

パーツ的には半透明の黒背景(以下、カバーって呼びます)とコンテンツという構成になっているので、何も考えずにカバーとコンテンツを束ねた、modal-content.tag のようなタグを作ってしまって、 mount して一番外側の divappendChild するという感じにしたかった。

ただ、ここで問題になってくるのはモーダルが重なれば重なるほど、カバーの色が濃くなっていってしまうということ。そんなたくさん重ねることもないだろうけど、モーダルが増える度に濃くなっていくというのは目に見えて明らかで、なんだかかっこ悪いなあということで対処方法を考えた。

f:id:BLThunder1991:20180722124152g:plain

トライしたこと

カバーをタグとして切り出してしまって、常にアプリケーション内にカバータグを1つだけ存在させるという方法をまず試した。

モーダルのタグが mount されたら、modal_open みたいなイベントを trigger してインクリメント、 unmount したら逆にデクリメントして、0になったらカバーを display: none させるみたいな実装。

一応これでもそれらしい動きをしたのだけど、今回の要件ではモーダルのサイズとか位置がいくつかパターンがあり、重なり方によっては一個奥で開かれているモーダルがカバーに覆われていないということが発生した。

まあ常に一番奥にカバーをおいているから当たり前なんだけど。

結局どうしたか

結局、 modal-content.tag 自身に cover というタグを内包させることにした。そして、モーダルが重なる度に、常に一番手前にある cover だけに色をつける、という方法をとった。

mount される度に自分が一番手前の cover かどうかを調べるっていう事も考えたけど、イマイチかなあと思ってやめた。自分の1つ手前のやつが消えたら色を変えるっていうのもやらなくてはならないので、 mount だけが色の決定のトリガーにはならない。どこかのカバーが消えたことと出たことに反応して自分の色を決定しなければいけない。

そのときに、Riot.jsの機能の一つである、Mixinというのを使ってcover タグのクラス変数みたいな使い方をしてみた。これが今回のエントリの本題になる。

MixInの中で、modal が閉じたり開いたりしたかどうかのイベントをlistenして、 自分が手前に来たら isDark みたいなフラグを立ててあげるようにした。

自分自身が unmount されるときは、 cover のリストからIDを取り除きつつ、閉じたことを trigger するという感じ。

import riot from 'riot';
const coverObservable = riot.observable();

let nextId = 0;
let ids = [];

const CoverEvent = {
  OPEN_MODAL: Symbol('OPEN_MODAL'),
  CLOSE_MODAL: Symbol('CLOSE_MODAL')
};


export default class CoverMixin {
  init() {
    this.coverId = ++nextId;
    ids.push(this.coverId);
    this.isDark = true;

    this.on('mount', () => {
      coverObservable.trigger(CoverEvent.OPEN_MODAL);
      coverObservable.on(CoverEvent.OPEN_MODAL, this.onOtherCoverOpen);
      coverObservable.on(CoverEvent.CLOSE_MODAL, this.onOtherCoverClose);
    });

    this.on('unmount', () => {
      _.remove(ids, (item) => { return item === this.coverId });
      coverObservable.off(CoverEvent.OPEN_MODAL, this.onOtherCoverOpen);
      coverObservable.off(CoverEvent.CLOSE_MODAL, this.onOtherCoverClose);
      coverObservable.trigger(CoverEvent.CLOSE_MODAL);
    });
  }

  onOtherCoverOpen() {
    this.toggle();
  }

  onOtherCoverClose() {
    this.toggle();
  }

  toggle() {
    if (_.last(ids) === this.coverId) {
      this.toDarken();
    } else {
      this.toLighten();
    }
  }

  toDarken() {
    this.isDark = true;
    this.update();
  }

  toLighten() {
    this.isDark = false;
    this.update();
  }
}

このMixinを cover タグに mixin しておけば、 mount されたときと unmount されたときに勝手に背景に色を付けるべきかどうかを判断してくれるという仕組みになっている。

イベントのやりとりもすべて、observable を中で持っているMixinの中で閉じているので、全体の observableに表示用のロジックが紛れ込むこともないので、結構良いのではと思っている。

cover をタグとして切り出さなくても、modal のタグにMixInすればいいんじゃないの、とかも思ったがただ後ろに半透明の黒背景出したいだけなのに毎回毎回カバー用のCSSとか処理を書くのもなあと思って切り出している。あと、 coverId っていうインスタンス変数的なものは追加されてしまうので、それを万が一上書きするような事があっても面倒だし。

全部のコードは以下。

github.com

まとめ

Riot.jsで困ったという話ではなくて、おそらく何を使っていても困ったと思うのだけど、Riot.jsではこういう風に表現できるかもねということを整理した。

本当は、CSSとかでシュッと処理できるのではないかとも思っているのだけれど、すぐには思いつかなかった。どこかで出会ったら書き直したほうが効率が良さそう。