第4回しろさとTT反省会

これは何?

チャリを買ったので3ヶ月練習して、しろさとTTというチャリを漕ぐ会に参加してきて思ったことを書く

参加は50kmの部門。

shirosato-tt.com

参加するまで

なんか世間ではzwiftという家でチャリを漕ぐやつが流行ってるらしいじゃね〜か、というインサイトを今年の夏頃に得て

チャリを...漕ぐカァ...という気持ちが高まり諸々を買い、せっかくなのでトレーニングして上のレースに出る意思決定をした。

zwiftを買ってよかったのはFTPというチャリ界の階級みたいなものに基づいて科学的な根拠のあるトレーニングができるので、根性論的なやる意味をいちいち考えさせられるような運動をさせられないのが良い

というか学生時代の部活の体力トレーニングって人間ごとにメニューを組む分けではなかったので、無意味で自己満足を育ててやっている感を出してるだけだなって思ってしまった

ちなみにFTPというのは1時間漕ぎ続けることができる限界のパワー(単位はワット)になる

練習など

練習メニューを組む上でとりあえずFTPを測らないといけないので、なんか測り方が色々あってその中でシュッと測れる RAMP testで測った

RAMP testはアスリート以外は基本的に高く出ることが多いらしい

どのみち練習メニューをこなした際にターゲットの心拍数ゾーンが設定されており、それより高く出ていればFTPの値が間違っていると考えることができるので下げたらいいと思う。

ちなみにやってみた結果は以下のようになった

8月:152w 9月:184w 11月:214w

練習メニューは目的に合わせてzwiftの初心者向けのトレーニングメニューであるFTP Builderというの一旦2ヶ月やった

途中、コロナっぽい風邪に罹って1週間休んだが概ねメニューは完遂した。

本番前

申し込みの時点では51kmあたり大体30km/hの1時間40分ぐらいを目標にしていたが

事前にzwiftや路上で漕いでみた感じでは 普通の姿勢で31km/h エアロポジションで32km/h ぐらいはいけるかなという感じだったので、 時速33km/hの1時間32分あたりを目標にした。

元々、クレアチンを取っていたが一旦飲まない期間を置いてから本番1週間前にクレアチンローディングをした。

ケトジェニックで体を慣らせば有酸素能力が一時的に上がるのでは?と思い本番2週間前から1週間ぐらいにやってみたが、科学的根拠に足る文献が無かったから今のなしで、ってなった

ただ糖質オフすると明らかに練習の負荷が高まってその後糖質をとるとめちゃ楽にこげる!ってなるから気分上の効果はあるかもしれない

本番&振り返り

チャリの会は初だったので若干不安だったがなんとかなった。

結果は1h34m30sだった

練習で50kmの距離をエアロポジション取り続けることは無かったので不安だったがずっと取り続けれたのはよかった。

心拍数のavgは166で1時間半のTTの場合はおそらくL4領域の心拍数に収まっていたらいいと思うので、そこらへんのコントロールはうまく行った説はある。

後半の足の前の筋肉がかなり"キてしまった"ので、尻で漕いでた感じがある。足がきてしまったのも一定のパワーで漕げていないことからスピードを維持しようとして不安定な出力をしてしまった感じがある。 あと、1時間半通しのトレーニングをあまりしていなかった。

zwiftで今漕いでいるパワー(ワット)が出るが、持っているチャリにはつけていないので、練習通りのパワーコントロールができていないという課題がある。

ケイデンスは安定はしてた気もするような、してないような?

気づき

とりあえずトレーニングをしてFTPを上げてくしかない

エアロポジションの研究はしたいが、ハンドルまわりを変えないといけないし計測しにくいので難しいなって思った

パワーメータは流石に欲しいかもしれない。エンジニアとして「推測するな計測せよ」というのは大事にしないといけないので、計測できる環境をまず作るか

来年の3月に第5回があるのでそれも出る。

最近はNix on raspberry pi zero をやった

イントロ

raspberry pi zeroをちょっと前に2枚買ったのが特に用途がない

強いて用があるとすれば、この前買ったserial通信経由でデータが取れるco2計測器がLinuxの方が読みやすそうだなってぐらい。 これはこのco2計測器が悪いわけではなく、macにマウントされるserial device?がちょっといまいちな挙動をしているからだ。

Amazon.co.jp: 国内生産 日本製 二波長CO2センサー搭載マイコン EPEA-CO2-NDIR-08 PC連携可 二波長NDIR方式 Dual Beam CO2モニター 二酸化炭素濃度計 : 産業・研究開発用品

というわけで 何かと開発する上で便利なので、Raspberry Pi OSにnixをいれていく。

余談だが、rasipbian OSはRaspberry Pi OSに名前が変わっていた。

install

Nixをいれるのは適当にやってもらっていいが、以下の行に注意する必要がある

nix/install.in at master · NixOS/nix · GitHub

"$(uname -s).$(uname -m)" の実行結果が Linux.armv6l_linux になることを期待しているが、 少なくとも自分の環境では Linux.armv6l になる

これは Linux.armv6l_linux が返ってくる環境が世の中にあるのかわからないのでバグなのかわからないが、armv6lのRaspberry Pi OSにNixを入れようとしている人間がzeroに近いことを演繹させてくれる有力な証拠である。

ちなみに NixOS on raspberry pi zeroをやっている人間はGitHubを見た感じでは何人かいることが観測できたので、そのうちやると思う。

build on pi

普通の環境では(ここでいう普通の環境とはflake-utilsのdefaultSystemsとか)「はい!あとはプログラムを書いて終わり!」となるが、ここはarmv6l、一切のcacheが降ってこない砂漠地帯、nix-shellが要求するbashInteractiveですらgccのビルドから始まってしまう。

というわけで gccとstdenvのビルドをやっていく。

まぁ時間さえあれば終わるでしょうと思っていてビルドを走らせていたわけだが、途中で止まってしまう。

どうやらメモリが足りなくなってOOMで落ちたっぽいエラーを観測した。足りないのは時間ではなくメモリ。

正直 パイゼロは500Mしかメモリがない、がしかし「20年前のPCでも500Mあったし流石にgccはビルドできるのは?」という気持ちも捨てがたい。そして「SD上にswapを増やしても大変な遅さになってしまうのでは?」と思いパイゼロ上でビルドするのはやめた。

なのでここからはmacでビルドしてラズパイに送る戦略をとる。

build on mac

ところでDockerDesktopという便利なものがある。何が便利かというと、マルチCPUアーキテクチャサポートがある

つまり armv6lのlinuxが豊富なメモリと屈強なCPUを積んだmacで動いてくれるわけだ。

今回は arm32v6/alpine Docker Hub にNixをインストールする戦略をとる。

余談だが NixのcrossCompile機能を使ってやるという手法もあるのだが、derivationが異なってしまう恐れを直感的に感じ取り今回はやめた。 具体的には crossCompileでビルドしたgccを使って ラズパイ上で他のものをビルドすること際に気を使う必要がある可能性を感じた、これは試していないからわからない

話を戻し、まずは bashをビルドしていく。ここで必要なのは時間と忍耐力で、具体的には一晩の時間とmacのファンの音を気にしない心だ。

ここで 一旦 ラズパイの方に できた bashを送る。 nix copy -s --to $ビルドされたbashのpath

送る際に because it lacks a valid signature と言われると思うので、nix.confに require-sigs = false を足して nix-daemonを再起動させる。

おそらく動くと思うし、bashをbuildしようとしてもbuildされずに先程送ったpathが返ってくると思う。もしビルドが始まった場合同一のderivationをビルドしようとしていない可能性が高いと思う。

あとはstdenvをビルドしていく。

あとはビルドするだけと思いきや、ここでstdenvの依存の中に含まれるpcreのtest phaseでコケてしまう。

「そんなわけがないだろう」という気持ちになるが、手元にはすでにコンパイル済みのgccがいるのでラズパイに送りさえすればビルドできるので試してみたところ pcreはビルドできてしまった。

ビルドできてしまったこと自体も「そんなわけがないだろう」という気持ちになったが、pcreがビルドされていれば後はmacのdocker側に持って来ればいいだけなので nix copy --from で持ってくる。もはやキャッチボールだ。

stdenvとbashInteractiveをラズパイ側に送りつけ、 nix-shell できることを確認する。

よかったですね

何故こういったことをやっていたのか忘れてしまったが、おおよそ、私の目的はビルドでプログラムの実行は副作用でしかないので、よかったですね。

pcre debug編

なぜpcreのテストが失敗したのか調査していくと pcregrepの -L オプションで失敗しているようだった。

pcreのソースコードを読んでいくとreaddirの挙動がおかしいように感じたので、疑似的なプログラムを書いて試してみると確かに動かない。

比較するために

  • mac
  • docker(armv6l)
  • docker(x86_64)

の三つの環境で疑似プロを動かしたところ armv6lでだけ動かない。

最初はoverlayfsあたりが悪さをしているのでは?と考えたがどうやら違うらしい。

そもそもマルチCPUアーキテクチャqemuを使っているので、そこら辺のワードと共に探っていくと以下のIssueに行き着いた。

gitlab.com

これは...ダメですね...

テーマは「情報収集について」

RSS

自分の場合、日常的なInputとして使っているのはRSS(Feedly)で大体以下のRSSかな

ほんとは他にもフォローしているブログがあったのだが、更新されなくなってしまった

まぁはてブの人気エントリは1ヶ月で2000ぐらいあったりするので大体それ見とけばいいとなっている 基本的にタイトルは全て追っていて、気になったり知らないことに関して書かれた記事は読むという感じ

Twitter

Twitterもソースとして当然使っているが、とはいえメジャーな技術の記事は上に含まれているような気もする。

なのでニッチな技術に関してはその第一人者をfollowしておくとかで有用、例えばNixなら Domen Kožar (@domenkozar) | Twitter とか

たまに海外記事のまとめをReplyで翻訳し始める人間もいるので、そう言った場合に有用。

AWS

他にはAWS ニュースレターとかもAWSのアップデートを追う上ではまぁまぁ有効、最近は新サービス開始時にTokyo regionもおま国されないのが嬉しい

nixpkgs

github.com

nixpkgsのcommit logとか適当に見ているだけでかなりの情報がある、これは流石に全部見れんが

GitHub

遭遇したIssueはとりあえずSubscribeしとくと便利、あまりfollow機能は使っていない

Web

あと、なんか普通に仕事してたりTwitter見ていたら、知らないことって結構出てくるので納得いくまで調べることが多い

shell.nixとdirenvでプロジェクトごとに補完をいい感じにする

概要

HERPでは shell.nix をgit repositoryのrootに置いて依存関係を解決しているが、PATH がprojectごとに設定されるだけなので 例えば kubectl の補完が有効になるわけではない。

その課題を解決するために shell.nixzshの補完もうまく済ませるワザップを今回は書く。

zsh completion について

zsh: 20 Completion System

zsh の completionの仕組みをざっくり書くと、 FPATHをいい感じにして compinit すれば FPATHから解決されるcompletion用のscriptが実行され補完される

手法

FPATH用のderivation

まず、completionを集めたderivationを作る。

buildEnv というderivationの特定のディレクトリの集合体を作る関数があるのでそれを使う

FPATH = "${nixpkgs.buildEnv {
     name = "zsh-comp";
     paths = buildInputs;
     pathsToLink = "/share/zsh";
   }}/share/zsh/site-functions";

FPATHの設定

上記で作った FPATH$HOME/.zshrc で追加された FPATH に足せばいいのだが

安易な方法として shell.nix にFPATHを足してしまうと、そのまま上書きされて既存の補完の全てを失ってしまう

なので、 project_FPATH のような環境変数に一時的に保存する。

このまま nix-shell --run zsh のように実行する場合は, ZDOTDIR をshell.nix中で上書きするなどのコードをを足せば問題ないのだが、 いちいち実行するのが面倒なので direnvを使っている場合は工夫が必要になる。

use nix
path_add FPATH $project_FPATH

以下の理由でこのコードは動きそうに見えて動かない(人によっては動く)

direnvは .envrc の評価をbash上で行っており、評価した結果の差分を既存のshellに足すような実装になっている。(コレは echo $0 してあげるとわかる)

実はzshFPATH は exportされていない変数なので (コレは echo ${(t)FPATH} でわかる、コレをlocal変数と言っていいのかはわからない) bash上で評価した際に存在していない変数として扱われFPATHが上書きされる

なので direnvの評価が始まる前、つまり ~/.zshrc などで export FPATH (typeset でも可) しておく必要がある

export FPATH してない人間向け対応

世の中には export FPATH していない人間もいるので、そう言った人が projectに入って direnv allow した瞬間に壊れて cd するのも困るのは不親切という考え方もあるので対応をする。(考え方によっては学習機会を奪っている。人間は困らないと進化しないので)

上記で書いたように 評価がbash上で行っているので export -p した中に FPATH が含まれていなければ export FPATH されていないことがわかる

よって以下のようになる

use nix

if export -p|grep "declare -x FPATH" ; then
  path_add FPATH $project_FPATH
fi

compinitの設定

あとは compinit するだけなのだが毎回 compinit していてはダルい(ダルい)

なので direnv がhookで評価した後にFPATHが書き変わっていれば compinit するようなhookを作ってあげれば良い

export COMPINIT_DIFF=""
_chpwd_compinit() {
  if [ -n "$IN_NIX_SHELL" -a "$COMPINIT_DIFF" != "$DIRENV_DIFF" ]; then
    compinit -u
    COMPINIT_DIFF="$DIRENV_DIFF"
    echo "compinited !"
  fi
}
if [[ -z ''${precmd_functions[(r)_chpwd_compinit]} ]]; then
  precmd_functions=( ''${precmd_functions[@]} _chpwd_compinit )
fi
if [[ -z ''${chpwd_functions[(r)_chpwd_compinit]} ]]; then
  chpwd_functions=( ''${chpwd_functions[@]} _chpwd_compinit )
fi

FPATH の diffを取ると言ったが色々考えた結果,nix-shell中でdirenv が実行されたときにcompinitされればいいので上記のようにした。(compinit以外のこともしたくなるかもしれない)

蛇足として一応書いておくが autoload compinit は他でするように

終わりに

nix-shelldirenv の組み合わせは環境を揃える手法として有名だが、実は補完まで揃えることができる。 各個人のzshrcに追記する必要はあるがオススメできる手法である。

余談

herp.careers

HERPのSREチームはnixを使って各種ツールの環境を揃えている。

KindleのアプリのUI悪い部分

概要

Kindleのアプリの体験が率直にいうと最悪なことはよく知られたことだが(ここで要出典と書こうとしたが「Kindle 使いにくい」をTwitterで検索するとたくさん出てくるのでここでは周知の事実として扱うものとする)

あまり言語化されていないようなので書く

一度読んだ本を最初のページから開くことができない

f:id:hiroqn:20220326231238j:plain

基本的に一度開いた本は読んだ途中のページから開かれる。それは当然いい機能だとは思うんだけど、ワンアクションで最初から開くことが何故できないのか疑問

読み終えた本、おそらく最終ページまで行った本は既読マーク(スクショで囲った部分)がつく

最後まで読んだという判定がありながら、本を開いた際に奥付けが表示されてユーザーが満足に思うと考えているのだろうか

ちなみに「未読にする」ボタンを押すと既読判定が消えるだけで開いた瞬間に既読になる、ジョークボタンか?

サマルとこれに関しては2点課題がある

  • ワンアクションで用意されていない
  • 最終ページまで行った本に対してのケアがない

しおり機能の誤判定が多い

f:id:hiroqn:20220326233113j:plain

スクショの赤線で囲ったあたりをタップすると、しおりを挟む機能がある

タップする、と簡単に言ったが再現性が非常に低く、おそらく画面とベゼルのぎりぎりのところをタップするとしおり機能が発動する、指が完全に画面内に入っていると駄目

f:id:hiroqn:20220326233101j:plain

ちなみに画面内をタップすると上のように「なんか色々できる画面」になる

実はしおり機能を使っていなんで、私の場合画面をタップする場合は100%2番目の画面になってほしいが結構な確率でこの「しおり」が発動する。

そしてしおりの解除がしたくてもう一度タップすると今度は2番目の画面になる

最悪だ...最悪ランキングの上位最悪体験である

別にしおり機能があることはいい、使う人もいるんだろう

この判定のピーキーさは本当にやばい、使ったら絶対わかる

絶対なんかあったはずで、しおり機能は例えば長押しするとか(現状長押しには何も割り当てられていない)、設定でしおり機能をオフにできるとか

表紙に戻るためのアクションが長い

f:id:hiroqn:20220326235522j:plain

「表紙に戻る」という行為はほんの一覧ページからできて然るべき、と言った内容は既に書いたが、実は本を開いている最中でさえ1アクションどころか3アクションかかる

スクショで示したように

  1. 画面の真ん中をタップする
  2. ハンバーガー亜種アイコンをタップする
  3. 表紙をタップする

の3手順かかる

さらに最悪ケースとして、稀に目次が細かく別れている本があるのだが、その本の場合「表紙」が出てくるまでスクロールする必要がある

必要なアクション数が多いことは最悪さの権現であるが、実は上記のフローに隠れ最悪UIが潜んでいる

それは2と3の距離が遠いということである

それだけ?と思うかもしれないが、やったらわかる、やってみなはれ鳥井信治郎

画面のアスペ比からわかると思うがこれはiPadであり(厳密には10.9inch のAir)私の指は11inchもないので片手で支えてもう片方で操作する

つまり2をタップする際に左手の指を使っているのだが(私の左手は左についている)、右手はiPadを支える状態になっていて右手は操作できない(しにくい)

なので3をタップする際にはiPadを持ち替えて右手でタップすることになる。わからん人間は仰向けになって寝ながら漫画読んでいる時を想像してくれ

あと、片手で全て操作したらいいのでは?って人間、買え!iPadを、でかいから

コレ、本当に最悪なんでこのデザインに決定した人のマウスを逆の手でしかクリックできないようにしてほしいし、実はちょっと前まで3のボタンが実は左にあったんでデザイン戻してほしい、切実に

サマリ

どこら辺にボタンがあると快適なのかを考えられてないなぁと感じるアプリは多い

私もiPadポートレートモードで持つこともあるし最強のボタン配置はないと思う

ただ、一部のゲームはボタン配置をいじれるようになっていて流石に体験がいいなってなる

あと、Desktop Webも同じ課題に向き合わなければならない

ちょっとした操作をするたびにポインタを左右に振らされるとゲンナリするし、その操作を何回もしなければいけない時には鬱になる、FPSじゃないんですよ

考えた結果それでも操作の距離が遠くなる場合、視線とポインタの位置を一致させる人が多いように感じるので、視線誘導を意識しながら配置すると良いと考えている

GitHubでrepositoryごとに権限が割り当ててある人間を探す

abst

GitHubの権限を真面目に管理することを考えると、やはりrepositoryに対してUserを紐付けることをやめたい。 つまりRepositoryに対してTeamを紐づける権限管理をやりたい。

しかし、Repositoryを作ったUserがadminとして設定されてしまう仕様や過去に適当に割り当ててしまっていた経緯から、いまだにRepositoryに対して割り当てられているUserを探して削除する必要がある。

今回はGitHubのGraphQL APIを用いて上記のようなRepositoryを探す

実装手法

以下のようなQueryにした。ORG_NAMEを書き換えること

query FindRepo($node_id: String) {
  organization(login: "ORG_NAME") {
      repositories(first: 20, after: $node_id) {
          totalCount
          pageInfo {
              endCursor
              hasNextPage
          }
          nodes {
              id
              name
              nameWithOwner
              collaborators(affiliation: DIRECT) {
                  edges {
                      node {
                          login
                      }
                      permission
                      permissionSources {
                          source {
                              __typename
                              ... on Organization {
                                  login
                              }
                              ... on Repository {
                                  nameWithOwner
                              }
                              ... on Team {
                                  slug
                              }
                          }
                      }
                  }
              }
          }
      }
  }
}

依存関係として、jq,ghが必要

TMP_FILE="$PWD/tmp.json"
DEST="$PWD/repo_list"
QUERY="$PWD/repo.graphql"

set -ex

gh api graphql -f query="$(cat $QUERY)" > $TMP_FILE
jq -r '.data.organization.repositories.nodes[]|select(.collaborators.edges|length > 0)|.nameWithOwner' < $TMP_FILE > $DEST
cat $TMP_FILE
while [ "$(jq -r '.data.organization.repositories.pageInfo.hasNextPage' < $TMP_FILE )" == "true" ]; do
  sleep 1

  cursor=$(jq -r '.data.organization.repositories.pageInfo.endCursor' < $TMP_FILE )
  gh api graphql -F node_id="$cursor" -f query="$(cat $QUERY)" > $TMP_FILE
  jq -r '.data.organization.repositories.nodes[]|select(.collaborators.edges|length > 0)|.nameWithOwner' < $TMP_FILE >> $DEST
  cat  $TMP_FILE
done

解説

Repository の affiliation: DIRECT にするとRepositoryに対してUserが紐づいた人が出てくる.

All collaborators with permissions to an organization-owned subject, regardless of organization membership status.

らしい

bashで雑にloopを回していく。

権限を取り除く

API経由でできなくもなさそうだが手で取り除いた。

正直、このコードはひどいな、と思いつつ...

for i in $(cat $DEST);do echo $i; sleep 2;done|xargs -n 1 -I @ open https://github.com/@/settings/access

ブログなどのコードはメンテされないので別のとこで面倒を見るためのリンク

scrapbox.io

財テク

このテーマ考えたの自分だけど、そんなに自分は資産運用に関してよく考えてないことに気づいた&そんなに資産がない

資産状況

NISA口座を開設した

この行動するまでに1年ぐらいかかった。しかしNISAは開設して終わりではない。入金して投資しなければいけない

今年中に終わることができるのだろうか

IDECO資料請求した

でも60歳まで引き落とせないのリスク高すぎるのでは?ってなって辞めた。

この制度、新卒で入った会社にずっといるタイプの人間じゃないと性格的に恩恵感じないのでは?それか個人事業主系の人

そもそも60歳って微妙すぎる。45歳ぐらいでFiredしたい人間には向いてない。制度として定年宣言をした段階で貰える&再加入不可でよくないか?

詳しくないので上のwazapもできるのかもしれない

Folio

folioやってる。130万ぐらい、そのうちロボアドが80万ぐらい。

NISAでやれって言われたらまぁそうってなる。

ふるさと納税

12月18日、ついにやった。

特に楽天経済圏にいる人間ではないが楽天を使った。

前はさとふるを使っていたが、ソフトバンク系のサービスは全て使わないようにしているんで辞めた。

生活費運用

私名義の共同の口座に定額入れる仕組みで運用している。家賃などはそこから落ちる。 あと B/43 | ラクして予算管理!家計簿プリカというサービスを使っている。共有のクレカが使える的なやつで、これはかなりベンチ

ついでに招待コード貼っておきます W4QDTL

もともと上記の共同の口座のキャッシュカードについているデビットカードで運用していたが不便だった。

B/43の不便点としては、スマホ決済対応してないのがある。

もともとKyashはQuickPayが使えて最近共有カードの概念を出してきたので、B/43も対応するんじゃないんですかね、知らんけど。

ちなみにKyashは初期使っていたけど、共有カードの概念がないのと資金決済法対応でサービスがガラッと変わったのでちょっと前に解約した。 まぁ色々察するところもあってしょうがないとは思うけど、便利な機能で客寄せしてコアバリューをガラッと変えてくる企業は私のポリシー的に使うことができない。