初速

自分で立てたマストドンインスタンスに人がこない。マストドンの本来の意義は情報の発信や保管を人に任せないという点で、それは自分のインスタンスに人がいなくても問題はない。

しかしインスタンスをわざわざ立てたきっかけはツイッターのユーザーストリーミングの廃止だ。アニメを見ながら大量かつ高速にツイートするアニメ実況がやりにくくなった。マストドンなら今までどおりの使用感で実況ができると思ったんだが、自分一人しかいないインスタンスでは実況しても何も楽しくない。実況の醍醐味は一体感だからだ。

マストドンユーザーで他にアニメを実況している人間がいないか探してみたが、そもそも 探す方法がない。プロフィール検索は存在しないし、地道に大手インスタンスのトップページで公開されているタイムラインからアニメ実況している人を探したが、pawooに一人いただけだった。

ツイッターからマストドンに人を引き抜くためには、初速が大事だ。クラスタを丸ごと同時に引き抜かないと定着しない。そのための方法を何か考えるべきだった。

というわけでアニメ実況したい人のためのインスタンスanimedon.chao.tokyoをよろしく。

嫌になる

今日はアホみたいなミスで待ち合わせに失敗してとても悲しかった。東京で指定の場所に時間通りに到着するのは僕のようなグズには難しい。

『君の膵臓を食べたい』はつまらなかったです。

明日も大学に行く用事があるのだが、昼頃には済むはずなので帰って洗濯をして休もう。疲れている。

Mastodonに自動ハッシュタグ機能をつけた

アニメ実況時は同じハッシュタグで継続的にツイートする。よってハッシュタグを保持し自動的に付加し続けてくれる機能は便利だ。作った。

やたらとトゥートの反映が遅いのはサーバーがイマイチだからかな…

この機能追加はReact+Reduxの処理階層を知っていれば全然難しくない。まずハッシュタグ入力欄と、そこへの入力を処理するaction, reducer, stateを作る(全部compose-formのコピー)。さらにCtrl+Enterによるトゥートを処理するhandleKeyDownにShift+Enterによって発火する別ルートのトゥート投稿処理を追加する。これもトゥートボタンによって発火する処理をほとんどコピー。そのルートの最後にあるのがこれ。

const status = getState().getIn(['compose', 'text'], '') + ' ' + getState().getIn(['compose', 'preservedHashtag']);

これだけが実質的に意味のあるコードだ。興味のある方はコミットログをどうぞ。

1年前のドワンゴインターンではJavaScriptが全然わからず(わからなかったのはJavaScriptだけではないが)チームメンバーに教えてもらっていたが、今では自力で触れるようになった。

Mastodonでハッシュタグ補完すると1文字目が勝手に確定する問題

Mastodon(v2.5.0rc1)でトゥート入力時にペーストでハッシュタグを入力すると、ハッシュタグ補完機能でハッシュタグの候補が表示される。それをEnterやクリックで確定して投稿すると、次のトゥートを入力するときに日本語入力を有効にしていても1文字目が勝手に確定される。

1文字目が勝手に確定されるという現象は割とよくあるやつで、slackでもTwitter公式でも発生した事例はある。しかし今回はハッシュタグ補完時のみという条件があるので、もしかしたらハッシュタグ補完が発生したときにはトゥート投稿時の投稿欄の情報リセット忘れがあるのかもしれない。現在ソースコードを確認中だ。

なおfriends.nicoでも同様の現象が起きることを確認済み。OSはUbuntu18.04で日本語入力はmozcだ。書いてて思ったが変換の方で何か悪さをしている可能性は十分ある。あるいはデスクトップ環境かも知れないし、ブラウザかも知れない。なかなか手強そうだ。

スプラップアンドビルド

※この記事は『極搾り ピーチ』を飲んで書かれた。

マストドンにelasticsearchをつけようと思ったらなんか壊れてしまったので作り直した。

なんか壊れてしまったというのは、マウント関連だ。リバースプロキシであるnginx-proxyは設定ファイルを外部から読み込むために、ホストの設定ファイル(./my_custom_proxy_settings.conf)をマウントしている。この状態で更にvolumes_fromでmastodon-nginxからnginx-proxyをマウントするとなんだかよくわからないがマウント関連っぽいエラーが出る。read onlyとかなんとか書いてあった。

この2重マウントは僕もわけがわからずやっているが、そんなことだからエラーが出るのは当然だ。面倒なので一回全部消してマストドンを立て直した。前回のデプロイから1週間ちょっとしか経っていないが、github上のデプロイガイドが書き換わっていて驚いた。mastodonの進化はまことに速い。

新しいdocker-compose.ymlはこうだ。今回は自分で改造することも視野に入れ、自前でビルドすることにした。なおmastodonのバージョンはv2.5.0rc1だ。

version: '3'
services:

  mstdn-nginx:
    image: nginx:1.11.10-alpine
    expose:
      - "9090"
    restart: always
    tty: false
    env_file: .env.production
    links:
      - web
      - streaming
    volumes:
      - ./setting/nginx/conf.d:/etc/nginx/conf.d:ro
      - ./setting/nginx/conf:/etc/nginx/conf/:ro
      - /var/www/certs:/etc/nginx/certs:ro
    networks:
      - common_link
      - back-mastodon
  db:
    restart: always
    image: postgres:9.6-alpine
    networks:
      - back-mastodon
### Uncomment to enable DB persistance
    volumes:
      - ./postgres:/var/lib/postgresql/data

  redis:
    restart: always
    image: redis:4.0-alpine
    networks:
      - back-mastodon
### Uncomment to enable REDIS persistance
    volumes:
      - ./redis:/data

  es:
    restart: always
    image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.1.3
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    networks:
      - back-mastodon
### Uncomment to enable ES persistance
    volumes:
      - ./elasticsearch:/usr/share/elasticsearch/data

  web:
    build: .
    image: tootsuite/mastodon
    restart: always
    env_file: .env.production
    command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000 -b '0.0.0.0'"
    networks:
      - back-mastodon
    ports:
      - "127.0.0.1:3000:3000"
    depends_on:
      - db
      - redis
#      - es
    volumes:
      - ./public/assets:/mastodon/public/assets
      - ./public/packs:/mastodon/public/packs
      - ./public/system:/mastodon/public/system

  streaming:
    build: .
    image: tootsuite/mastodon
    restart: always
    env_file: .env.production
    command: yarn start
    networks:
      - back-mastodon
    ports:
      - "127.0.0.1:4000:4000"
    depends_on:
      - db
      - redis

  sidekiq:
    build: .
    image: tootsuite/mastodon
    restart: always
    env_file: .env.production
    command: bundle exec sidekiq -q default -q mailers -q pull -q push
    depends_on:
      - db
      - redis
    networks:
      - back-mastodon
    volumes:
      - ./public/packs:/mastodon/public/packs
      - ./public/system:/mastodon/public/system
## Uncomment to enable federation with tor instances along with adding the following ENV variables
## http_proxy=http://privoxy:8118
## ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
#  tor:
#    build: https://github.com/usbsnowcrash/docker-tor.git
#    networks:
#      - common_link
#      - back-mastodon
#
#  privoxy:
#    build: https://github.com/usbsnowcrash/docker-privoxy.git
#    command: /opt/sbin/privoxy --no-daemon --user privoxy.privoxy /opt/config
#    volumes:
#      - ./priv-config:/opt/config
#    networks:
#      - common_link
#      - back-mastodon

networks:
  common_link:
    external: true
  back-mastodon:
    external: true

注目してほしいのはmstdn-nginxのvolumesでホストマシンの/var/www/certsをマウントしていることだ。nginx-proxyでもホストマシンの同じディレクトリをマウントしている。2重マウントを解消し同じディレクトリをマウントするようにした。

elasticsearchはデフォルトで日本語対応してません。日本語対応プラグインを入れるのはちょっとしんどそうなのでまた今度やります。

ぶっ壊してまたイチから作ってというのを繰り返せるのは楽しい。無限にやりたい。

Ubuntu18.04はlibinput

※この記事は『本搾り オレンジ』を飲みながら書かれた。

昨日の記事の続きだ。新しいデバイス名を指定することで変換行列を指定することには成功した。しかし奇妙な現象が発生した。Kritaで絵を描くとき、細い線が引けないのだ。よく調べてみると、筆圧が5%を超えるまでクリック判定が発生していなかった。これをつぶさに調べる過程でデバイス名が変わっていた理由も判明した。

なぜUbuntu18.04にアップグレードするとデバイス名が変化していたのか。なぜ筆圧とクリックの挙動が変わってしまったのか。それはlibinputのせいだ。libinputはデバイス入力ドライバで、xinputの奥で動いているものらしい。16.04では液晶タブレットはevdevドライバで動いていた。18.04ではlibinputドライバが導入され、液晶タブレットの管理もlibinputに引き継がれたようだ。

考えるのが面倒だったのでlibinputを消したら解決した。

sudo apt purge xserver-xorg-input-libinput

libinputを消したらマウスの加速プロファイルが変わってしまって違和感があった。GNOME Tweaksから設定をFlatに戻したら直った。

今日のUI心理学

やろうと思ったんですが、ゲシュタルトの法則を一つずつ紹介していくだけだとクソつまんないのでもうちょっと面白いところまで読み進むのを待っててください。

Ubuntu18.04へのアップグレードに伴うデバイス名の変化

Ubuntu16.04で液晶タブレット(UGEE HK1560)をデュアルディスプレイで使うとき、ペンタブレットの入力を片方のディスプレイのみにマッピングするためにはxinputの”Coordinate Transformation Matrix”プロパティを使う。

私の場合は左のディスプレイ(液晶タブレット)が1920×1080で右のディスプレイが2560×1440だ。つまり液晶タブレットの入力はそのままだと2つのディスプレイをつなげた4480×1440の長方形にマッピングされる。これを左のモニターのみにマッピングするためには、x座標0~4480を0~1920に、y座標0~1440を0~1080に写像するような変換行列を用いる(3行3列の1はたぶん筆圧は無変換っていう意味だったと思う)。

さて、これを実行するコマンドは
xinput set-prop "UC-Logic TABLET MONITOR Pen" --type=float "Coordinate Transformation Matrix" 0.428571 0 0 0 0.75 0 0 0 1
だっ。Ubuntu16.04では。

Ubuntu18.04にしてからこのままのコマンドでは以下のようなエラーを吐くようになった。

X Error of failed request:  BadMatch (invalid parameter attributes)
  Major opcode of failed request:  131 (XInputExtension)
  Minor opcode of failed request:  57 ()
  Serial number of failed request:  19
  Current serial number in output stream:  2

なんだこれは?ググっても全然わからない。そもそもLinuxでペンタブレットを使おうという変態の絶対数が少ない。

xinputでデバイス名を確認したらこうなっていた

⎡ Virtual core pointer                    	id=2	[master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer              	id=4	[slave  pointer  (2)]
⎜   ↳ UC-Logic TABLET MONITOR Mouse           	id=10	[slave  pointer  (2)]
⎜   ↳ E-Signal COUGAR Minos X3                	id=11	[slave  pointer  (2)]
⎜   ↳ E-Signal COUGAR Minos X3                	id=12	[slave  pointer  (2)]
⎜   ↳ LingYao ShangHai Thumb Keyboard         	id=16	[slave  pointer  (2)]
⎜   ↳ UC-Logic TABLET MONITOR Pen Pen (0)     	id=18	[slave  pointer  (2)]
⎣ Virtual core keyboard                   	id=3	[master keyboard (2)]
    ↳ Virtual core XTEST keyboard             	id=5	[slave  keyboard (3)]
    ↳ Power Button                            	id=6	[slave  keyboard (3)]
    ↳ Power Button                            	id=7	[slave  keyboard (3)]
    ↳ Sleep Button                            	id=8	[slave  keyboard (3)]
    ↳ UC-Logic TABLET MONITOR Pen             	id=9	[slave  keyboard (3)]
    ↳ Mistel MD600                            	id=13	[slave  keyboard (3)]
    ↳ Mistel MD600                            	id=14	[slave  keyboard (3)]
    ↳ LingYao ShangHai Thumb Keyboard         	id=15	[slave  keyboard (3)]
    ↳ E-Signal COUGAR Minos X3                	id=17	[slave  keyboard (3)]

理屈はわからないが、なぜかこれまで使っていたデバイス名”UC-Logic TABLET MONITOR Pen”はキーボード扱いになっていた。その代わりに”UC-Logic TABLET MONITOR Pen Pen (0)”という怪しげなデバイスが出現している。先ほどのコマンドのデバイス名をこちらに入れ替えたところ、成功した。

LinuxでHK1560は普通に使える。筆圧も取れる。ワコムの同サイズ製品は18万円するのに対してHK1560は現在4万円だ(こちらはFHDであちらは4Kだが)。ガラスの厚みによる視差は液タブの宿命として当然あるが、それはワコムだろうとゼロにはできない以上程度の問題でしかない。発色が悪いと言われている(おそらく1677万色ではない)が、僕はそもそもきちんとキャリブレーションされたモニターを一つも所有していないのでこれを問うのは無意味だ。ペン先の沈み込みもよく不安がられる要素だが、ワコムの飛び出したり引っ込んだり不安定なペン先よりは弾力のあるこちらのペンの方が描きやすく、筆圧も自然につけられる。ワコムはドライバが不安定だと言われるが、こちらはLinuxで幅広く使われているxinputで作業中のトラブルは一度もない。

描画ソフトにはKritaを使っている。非常に大きな特徴として消しゴムツールが存在しない(全てのブラシツールに消しゴムモードがあり、オンオフして使う)ことが挙げられるが、慣れればどうということはない。

実はメインマシンをUbuntuに変えるときにこの辺りの用途がきちんとこなせるか不安だったのだが、マッピングを解決するだけですぐに使えたことで僕の中でのUbuntuへの信頼が高まった。

今日のUI心理学

2.2 類同

見た目が似ているものはグループとして見える。当たり前だね。小学生がやるみたいにメニューの項目で1つずつ色を変えたりしてはいけないということだ。

痛恨のミス

今日はポノック短編劇場『ちいさな英雄-カニとタマゴと透明人間-』を見てきた。事前にチケットを取ってからいったが、劇場の端末が反応しない。おかしいなと思って確認したら別の場所の劇場のチケットを取っていた。もう間に合わない時間だったので仕方なく行った劇場のチケットを取り直したが、1400円を虚空に溶かしてしまった。南無。

TI8はOGが優勝した。2-2でむかえた5ゲーム目、OGが選択したヒーローは癖が強かったが、anaのEmber Spiritが移動スキルを存分に活用し、死にそうで死なないまま戦闘に参加し続けることで勝利を手繰り寄せた。

7秒の時点でHPを入れ替えるスキルによってかなりHPを減らされるが、即座に移動スキルで右上に退避。短時間無敵になるアイテム(上空に巻き上がっている)の効果中に味方に安全を確保してもらう。その後回復アイテムですこし回復を入れたあと26秒から高速斬撃のスキルで再参戦。さらに30秒には移動スキルで残った敵に飛び込む。ここで敵の増援が瞬間移動アイテムで飛び込んで強力な範囲攻撃を放つが、ギリギリ死なない。高速斬撃スキルと無敵アイテムで数秒間しのいだあと歩いて下がるが、高速斬撃スキルをギリギリの間合いから放ってキル。

惚れ惚れするムーブだ。もちろん敵味方総勢10人が入り乱れて戦っているので偶然による部分も多いだろうが、体力が少ない状態でもスキルで飛び込む判断には度肝を抜かれた。

それにしてtwitchの切り抜き機能マジで便利だな。ニコニコにも欲しい。

ンギモチィィィ

※この記事は『秋梨 チューハイ』を飲んで書かれた。

JavaScriptで文字列の入った2次元配列をcsv風に結合する関数。最初はforループで以下のようなコードを書いた。

しかしこの方がずっとスマートだ。

そもそも上のようなコードを書くなという話。

ちゃんとUI心理学をやりたいのだが、今日は時期が悪い。何かというとTI8決勝だ。TI8というのはThe Internatinal 2018の略で、Dota2というPCゲームの世界大会だ。Dota2はLoLと同ジャンルで、この大会の賞金総額はe-sports界で1位だ(2500万ドル)。

1年間の各種大会の実績で8チームが招待され、加えて10チームが各地域の予選で出場権を獲得する。ある時期を過ぎてからメンバーを入れ替えたチームは招待を受ける権利を失う。1チーム5人なのだが、メンバーの入れ替わりが非常に多くそれを問題視したValve(開発元・TI運営)によってメンバー変更にペナルティが課されている。

面白いのは3位以上が確定している3チームのうち2チームはかなり遅い時期にメンバーを入れ換え、予選を勝ち抜いて出場してきたチームだ。世界トップクラスの選手になると、連携のために重要なのは練習ではなく相性ということだろうか。

OG

ヨーロッパのチーム。TI6とTI7の間のシーズンの大規模大会で全て優勝しTI7の優勝候補だったが、7位に終わる。その後midのanaが脱退し、長い低迷期に入る。TI8の3ヶ月前にFlyとs4も脱退するが、anaが復帰。予選を突破して本戦に出てみたらなぜか破竹の勢いで勝ち進み、グランドファイナル進出を決めている。

EG

TI5優勝。TI7は9位。本拠地は北米。メンバーはヨーロッパ。引退してコーチに回った選手をまた戻してみたり、かと思えばそのために優秀なmidプレイヤーを他のポジションに移動したりと謎の迷走を続けていたが、OGを離脱したFlyとs4を獲得して予選突破。

PSG.LGD

TI7は4位。中国人4人とマレーシア人1人のチーム。中国は強いチームが多い。シーズン中盤にメンバーが入れ替わって以降躍進し、招待枠2位で参加している。

もしグランドファイナルがEG vs OGなんてことになったらOGの元プレイヤーが2チームに別れて対戦するということになって面白い。