Posts for: #Life

戦略シミュレーションと特性

ストレッチ

今日の開脚幅は開始前158cmで、ストレッチ後161cmだった。先週よりやや数字が悪くなった。それでも先週はストレッチを受けていても体全体のだるさのようなものを感じていたのが、今回はちゃんと筋を伸ばしている感覚があって先週の体調の悪さはなくなったように思える。右股関節周りの詰まりに加えて、右前ももの張りがいつもより大きかった気がする。毎週ストレッチを受けていると物理的な体調の良し悪しもわかるのがよい。

わざと負ける理由

一昨日からリアルタイム対戦 にはまっている。数をこなしていてわかってきたことがたくさんある。戦略シミュレーションゲームはやればやるほど学びがある。

  • パーティーの特性によって相性のよい対戦相手とそうじゃないのがある
    • リアルタイム対戦のマッチングは選択できないのでマッチングしないと相手がわからない
    • 相性の悪い相手だとマッチング時点で辞退する (負けを認める) 相手もいる
  • こっちの戦略に呼び込むための布石がいる
    • 3つぐらい戦略を用意して最終的にどの戦略に呼び込むかを相手の動きをみながら考えないといけない
    • キャラを動かす制限時間が15秒なのでわりと忙しい
    • こちらの布石にはめて最終的に勝てると達成感がある
      • 中盤まで負けていて向こうに勝ったと思わせて逆転できるとなお嬉しい
      • ダークドレアム は奇数ターン (1, 3, 5, 7 …) ごとに攻撃力・守備力・すばやさ・かしこさが1段階上がるバフがかかる
        • ダークドレアムはすばやさが低いので徐々にすばやさが上がっていって先制できるようになると最後の1手違いで勝つ状況が出来上がる
        • ダークドレアムで5ターンまで戦闘を継続できれば勝率が高い
  • すばやさの高いパーティーには何もできないから勝てない
    • 高すばやさ (且つ、高火力または状態異常) パーティーには絶対に勝てない
      • リアルタイム対戦でダークドレアムがあまり使われていない理由だと思う
    • 初手前にパーティーの半分ぐらいがやられている
    • 相手の攻撃が届かない初期配置がないので絶対に防げない
  • 状態異常攻撃の主体パーティーは対戦していておもしろくない
    • 混乱・麻痺・眠り・魅了といった状態異常になると2ターン何もできない
    • 状態異常攻撃 + 高すばやさのキャラの攻撃を防ぐ方法はない
  • パーティー編成のウェイト制限がうまく調整されている
    • 高ランク (ステータス高い) のキャラばかりを編成できないようにウェイト制限がある
    • これにより、パーティー編成が4人か5人かにわかれる
    • 低ランク (ステータス低い) のキャラはウェイトも低いので5人目には入れやすい

本題のわざと負ける理由だが、わかってきた。リアルタイム対戦のマッチングは同じランク内で行われる。上位のランクになればなるほど、対戦相手も強くなる (強くなければ上位のランクに上がれない) 。一定量のポイントを獲得するとランクアップしていけるが、負けるとポイントが下がるペナルティがつく。一定のランクで勝ち負けを繰り返すとそのランクに留まり続けるということができる。私も自分の限界までランクアップしてみて気付いたのは周りも強いので限界に到達すると勝ったり負けたりを繰り返す。ここで別のルールで勝った回数に応じてコインが支払われるボーナスがある。強い人が低いランクで勝ち数を稼ぐのは限界に近いランクで勝ったり負けたりを繰り返すよりもはるかに効率がよい。それはリアルタイム対戦のマッチングに時間制限があるからなおさらそうなる。実力が均衡した相手と時間をたくさん使って2勝3敗を繰り返すよりも、わざと負けながら弱い相手に勝ち続ける5勝?敗を繰り返す方が絶対数としての勝ち数を稼ぐには効率がよい。おそらく負けたときのペナルティがあるランクからわざと負ける人が現れ始めていると思う。なるほどなぁ。

Kubernetes Clients のサンプル実装

23時に寝て7時半に起きた。夜中も2回ぐらい起きる。暑さでまいってきた。

ストレッチ

今日の開脚幅は開始前159cmで、ストレッチ後162cmだった。数字は悪くない。いつもはストレッチを受けていると疲労しているところが伸びることで体が軽くなっていく感覚があるのだけど、今日は体全体がだるくてストレッチを受けていてもなんかしんどいなぁとだるさを感じていた。コロナに感染してないと思うけど、夏バテの状態をそのままストレッチにも持ち込んだような感覚があった。腰の張りや肩甲骨の硬さなどが少し気になったかな。トレーナーさんには立ったときの姿勢が少し前よりで重心のバランスがよくないといったアドバイスをされた。とくにどこが悪いというわけでもないのになんかしんどい。

Kubernetes Clients のサンプル実装

Kubernetes Clients の調査 の続き。java クライアントを使って minikube でいくつか動かしてみた。openapi で生成した rest api クライントが提供されている。デフォルト設定でも minikube で普通に動いたのでおそらく裏で $HOME/.kube/config をみたり /var/run/secrets/kubernetes.io/serviceaccount/token を読み込んで認証ヘッダーに設定してくれたりするのだと推測する。

public ApiClient getKubernetesClient() throws IOException {
    var client = Config.defaultClient();
    io.kubernetes.client.openapi.Configuration.setDefaultApiClient(client);
    return client;
}

このクライアントを使って java/kubernetes/docs/ 配下にある api インスタンスを生成する。例えば、cronjob や job を扱うならば BatchV1Api というドキュメントがある。BatchApi だけでも3つのドキュメントがあるのでちょっとやり過ぎな気もする。

  • BatchApi.md
  • BatchV1Api.md
  • BatchV1beta1Api.md

kubectl コマンドで使う cronjob から手動で job を設定するのを実装してみる。

$ kubectl create job --from=cronjob/my-schedule-job my-manual-job

細かい設定はちゃんと調べないといけないけど、一応はこれで動いた。cronjob のオブジェクトを取得して job のオブジェクトを生成して create するだけ。

var api = new BatchV1Api(this.getKubernetesClient());
var cronJob = api.readNamespacedCronJob(cronJobName, NAMESPACE_DEFAULT, null);
var ann = Map.of("cronjob.kubernetes.io/instantiate", "manual");
var metadata = new V1ObjectMeta().name(newJobName).annotations(ann);
var spec = cronJob.getSpec().getJobTemplate().getSpec();
spec.setTtlSecondsAfterFinished(10);
var job = new V1Job()
        .apiVersion(cronJob.getApiVersion())
        .kind("Job")
        .spec(cronJob.getSpec().getJobTemplate().getSpec())
        .metadata(metadata);
var result = api.createNamespacedJob(NAMESPACE_DEFAULT, job, null, null, null, null);

手動で作成した job の pod は終了後にゴミとして残ってしまうので ttl を設定すれば自動的に削除できることに気付いた。

spec.setTtlSecondsAfterFinished(10);

k8s クラスターの内部、つまり pod 内からリクエストするには ServiceAccount permissions を適切に設定しないといけない。ひとまずローカルの minikube で super user 権限にしたらリクエストはできた。実運用では適切なロールを定義して適切に権限設定しないといけない。

kubectl create clusterrolebinding serviceaccounts-cluster-admin \
  --clusterrole=cluster-admin \
  --group=system:serviceaccounts

不思議の国のスモールオフィス

23時に寝て7時に起きた。今週は不規則な生活をしたのでバテた。

ストレッチ

今日の開脚幅は開始前156cmで、ストレッチ後160cmだった。先週よりちょっと数値が悪くなった。自覚症状はなかったけど、ストレッチをしてみると右腰の張りがそこそこあることに気付いた。自覚症状のない疲労に気付けるのがストレッチのよいところの1つでもある。

スモールオフィスの内覧

たまたま 起業プラザひょうご さんのスモールオフィスに空きがあるのをみつけたので内覧に行ってきた。電話したらとくに予約は取らなくてよいのでいつでも来てくださいと言われたのでアポなしで17時頃に行くことにした。現地のビルに行ってみたが、ビルが工事していて入れる状態ではない。なんかおかしいと思って調べたら地図には全然違う場所が示されていた。後で知ったことだが、2020年8月に移転していた 。前に起業プラザひょうごさんに2-3回行ったことがあったけど、それは移転前だった。その後、移転したことを全く知らなかった。

このコワーキングスペース兼レンタルオフィスが三井住友銀行神戸本部ビルという旧居留地の真ん中に18F建ていう、この付近ではトップレベルの高層ビルと言える。そんなビルの2Fという「ん?」という場所にある。おそらくビルの名前から三井住友銀行の自社ビルだろう。1Fには銀行の窓口があり、窓口の前を横切る形でエスカレーターを上がると起業プラザひょうごさんのコワーキングスペースがあった。入り口には警備員さんが立っていて入ろうとすると「会員証をみせて」と止められた。内覧にきた旨を伝えると通してくれた。銀行のビルなので休日でも警備員さんが控えている。

2Fにエスカレーターで上がり、受付で内覧にきたことを伝えるとそのまま (おそらくアルバイトの) 若いお兄さんがあちこち案内してくれた。興味本位で「素朴な疑問なんだけど、どういう経緯で銀行の自社ビルの2Fの空きスペースみたいな場所を間借りできたんですか?」と聞いみたら、さすがにそれは分かりませんと返ってきたw

普通のオフィス (5.6㎡) と広いオフィス (8.4㎡) の2つに空きがある。

空きスペースをパーティションで区切っただけの簡易的なオフィスではあるけど、家賃は税込でそれぞれ 23,595 円と 33,275 円になる。登記さえできれば、オフィスの体裁は私にとってそこまで重要ではない。物理的なセキュリティの懸念として壁の上によじ登ることができるのはあるけれど、扉には鍵がかかる。床面積から比較するとレンタルオフィスとしては周りの平均よりも半額から1/4ぐらいの破格の価格設定と言える。一通り話しを聞いてみて引越し先として検討できるかどうかを確認していた。私にとっての一番の課題はこのビルに入れる時間帯が制限されていること。私は平日は7時台にはオフィスにいるし、夜も遅かったら3時ぐらいまで作業をするときもある。外的要因で時間の制約を課せられるのが私にとってはストレスとなる。22時をまわることは月に数回程度しかないからまだ譲歩できても朝9時というのは始業が遅過ぎる。

  • 平日: 9:00 - 22:00
  • 土日祝: 10:00 - 20:00

顧問のはらさんとも相談して懸念がなければ、審査を受けるだけ受けてみてもよいかもしれない。但し、三井住友銀行の拠点ビルとも言えるところにあるコワーキングスペースなのでうちみたいなマイクロ法人は審査が通らない可能性も高いと思われる。過去に三井住友銀行で法人口座開設の申請を出してお断りされた実績もあるのでそれを思い出してた。

外部の人を招いて無償の勉強会を開催してよいかどうかを確認したところ、会議室の予約さえとれれば開催してよいとのこと。さらに会議室の利用料は無料とのこと。会議室は定員6名が2部屋、10名が1部屋、20名は1部屋の合計で4部屋ある。定員20名の会議室と聞くと「はぁ?」って感じでそこもみせてもらった。広い部屋のスペースを贅沢に浪費した構成だった。「こんな広い部屋の会議室って普段使うんですかね?」と質問したら使っているところをみたことないと返ってきて笑ってしまった。定員20名の会議室でどんな会議をやるねん?オフラインの外部勉強会をやるとしたらスペースが広くて快適そうな場所ではあった。あと後ろの方はモニターみえないよね、おそらく。

コーポレートファイナンスの入門

0時に寝て6時に起きて7時半に起きた。

ストレッチ

今日の開脚幅は開始前158cmで、ストレッチ後162cmだった。まだ右腰と右股関節、両腕の張りは少し残っているものの、先週末の田んぼ仕事の疲労はかなり抜けた。今週は暑くて家に帰ってきたらエアコンをつけてだらだらしていたのであまり数値はよくならないんじゃないかと思っていて、実際に開始前の数値はいま一つだったんだけど、ストレッチを受けたらいつも通りに戻った。トレーナーさんと雑談しているときにふと「毎日パソコンを使いますか?」と質問を受けた。トレーナーさんからプログラマーの自分にとってそんな質問をされるとは予想外で思わず吹き出して笑ってしまった。その質問は「毎日水を飲みますか?」と私にとっては同じですよと答えた。トレーナーさんも愚問だったと理解して一緒に笑ってた。

もてなしだけではもう食えない

第7章 ホテルが客を動かせ

ホテル側が自分たちの問題を解決するために客の行動を制御するといった展開になっている。米国のスーパーマーケットでは Express Lane という、購入品目が少ない客向けに手早く決済するためのレジが設けられているらしい。日本にはないのかな?この運用には客に学習コストを強いるのが欠点となる。キャパシティ問題の問題解決のアプローチは次の3つになる。

  1. キャパシティを増やす
  2. 供給を変える
  3. 需要を変える

本章の展開としては3番目の客側の導線や行動を変えてしまう方法で需要を変える手法が説明されている。本題ではないけど、さらっと出てくる説明にも納得感がある。ダメなホテルの共通点として、他社でうまくいった改善策、ベストプラクティスに飛びつき、それ以上考えようとせず、問題の本質を理解しようとしない。そういうホテルはコンサルタントが去ってしまうといずれでダメな経営に陥るとある。ホテルに限らず、ダメな会社の特徴だと思う。

客にピーク時の利用を避けてもらうための施策として次の2つがある。

  • 混雑することをあらかじめ伝えておく
  • 混雑を避けることのインセンティブをつける

ホテル側が客の行動をコントロールするのは構わないが、客にとってそれが不利益にならないように配慮する必要がある。人間の心理として混雑することがあらかじめわかっていればクレームにならず許容できたりする。人は不意に混雑に出くわして不満をもつことが多いという。そういった人の心理を利用して人の行動を制御して経営に生かすという考え方は比較的新しい研究領域である。行動経済学などもその分野の1つで、古典経済学では人は合理的に行動するとされてきた。しかし、現実では必ずしもそうではないことも行動経済学によってわかってきた。

第8章 リスクを知らないリスク

親会社の不動産会社からリスク管理報告書を提出しろという業務に沿ってリスクマネジメントについての話題が出てくる。契約の話しだったり、建築に関する話しだったり、あまり一般的な経営とは異なる内容にみえる。余談だけど、過去にうちの会社で業務内容が変わったにも関わらず、契約内容を更新せずに更新された新たな業務を継続してうまくいかなかった経験がある。うまくいかなかったときに原点に立ち戻る場所が契約であり、契約を曖昧に扱うと後でしっぺ返しがあるという失敗をまさに経験した。ふりかえりをするときにそもそもの基準が適切でないとその反省や改善点も曖昧になってしまうという話し。

さて、リスク管理報告書のアウトラインとして次の用語が出てくる。

  • ハザードコントロール
    • ハザードとは危険を生じさせるもののこと
    • ホテル経営だと、食中毒を防ぐ施策とか、横領できないように決済承認に2名以上必要とか
  • ペリルコントロール
    • ペリルとは事件・事故のこと
    • 起きてしまった事件・事故から最小限の損害・被害に食い止める施策
  • ロスコントロール
    • ロスとは事故発生時に発生してしまった経済的損失のこと
    • 具体的には保険購入であり、どんな保険にどのぐらいの補償額で加入するかになるが、これがなかなか難しい

peril という英単語の辞書を引くと、差し迫った危険という意味が出てくる。リスク管理の文脈の用語と英語の意味はやや違うのかもしれない。

第9章 タイムバリューを理解せよ

親会社に投資ファンドからホテルの買収提案があり、ホテルの事業価値を測るコーポレートファイナンスの話題が出てくる。上場企業であれば株価 x 発行済株式数で時価総額がすぐにわかるが、未上場企業の価値を査定するのは難しいという説明からその手法が紹介される。

  • 類似業種比準方式
    • 上場している同業者の株価を参考にする
    • 但し、ビジネスモデルを無視して業種だけで比較しようとしても単純比較はできない

不動産を所有しているかどうかで株式評価は大きく異なる。単純に不動産をもっていればよいというわけでもなく、資産と負債のバランスが取れているかが大事。「また貸し」のことを業界用語で転貸 (サブリース) と呼ぶ。

  • 純資産方式
    • 会社のもっているものを全部売って借金を返した残りのお金という評価方法
    • 貸借対照表の資本がマイナスになっているとすべてを換金しても負債が残る = 債務超過

株価の利回りを株価収益率 (Price Earnings Ratio: PER) と呼ぶ。時価総額 / 純利益で計算される。この計算式から時価総額を知りたければ、純利益 x PER で計算できる。比較可能な会社の PER がわかれば未上場会社の株価を計算できる。但し、PER は会社が未来永劫事業を継続させることを前提としている。会社の継続性に疑義があると PER を用いる根拠がなくなる。株主に説明するときの利益とは、正式には 税引き後当期利益 になる。この金額から配当がなされる。うちの会社だとざっくり粗利から20-30%ほど (法人税 + 消費税) 引いたものが税引き後当期利益になる。会社が予定する配当額は同じだが、株価をディスカウントすることで配当の利回りをよくするという考え方を リスクプレミアム と呼ぶ。会社の展望や事業の不確実性を数値化したとみなすことができる。

  • 株価1000円で配当額が20円だと、利回りは2.0%
  • 株価500円で配当額が20円だと、利回りは4.0% (この 2.0% の差がリスクプレミアム)

いま現在もらえる現金の1万円は1年後もらえる1万円よりも価値が高いと言える。それは1年後にはもらえないかもしれないリスクや運用機会損失リスクが含まれるから。その価値をどの程度低く見積もるかを 割引率 と言う。この割引率を用いて将来の現金をいまの現金価値に置き換える評価方法を DCF (Discounted Cash Flow) 法 と呼ぶ。仮に割引率を10%とすると、1年後の100万円をいまの価値にすると、100 / (1 + 0.1) = 90.9 万円になる。2年後の100万円だと 100 / (1 + 0.1)^2 = 82.6 万円になる。

本文中ではこの計算式を使って年間の利益と割引率を考慮した現在価値をエクセルでモデル化している。python で書くと次のようになる。

>>> def f(profit, discount_rate, year):
...   return profit / pow((1 + discount_rate), year)
>>> for i, profit in enumerate([100, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165], 1): i, round(f(profit, 0.1, i), 1)
... 
(1, 90.9)
(2, 99.2)
(3, 93.9)
(4, 88.8)
(5, 83.8)
(6, 79.0)
(7, 74.4)
(8, 70.0)
(9, 65.7)
(10, 61.7)
(11, 57.8)

例えば、割引率が10%で5年後の利益が135万円ならば、その現在価値は83.8万円になる。本文の中ではこの金額が投資ファンドが提示している金額だとだいたい一致していることから、これ以上の精度の高いモデルを作らないといけないみたいなストーリー展開になっている。いずれにしてもパラメーターの変数の精度が高くないと適切なモデルとは言えない。割引率を用いた現在価値を計算する考え方を タイムバリュー (時間の価値) と呼ぶ。意思決定が遅れるほどプロジェクトの収益化も遅れるため、割引率を計算する現在価値が小さくなっていくという考え方ができる。

1年ぶりの草刈り

1時に寝て5時に半に起きた。朝から夕方まで田んぼの草刈りをしていた。

草刈り

タイトルに1年と書いたけど、厳密には1年も経っていない。2021年10月以来の草刈り になる。本当は小まめに田んぼの手入れをしていれば、草場になんかならない。

6時から草刈り機を使って草刈りを開始。もう1時間早く起きて5時から始めたらよかったと思った。夏は10時まわると暑さが厳しくなるので作業は10時までに終わらせるのがよさそう。今回は6時から11時前まで草刈りをやって6割程度を刈り込んだ。草刈り機は2サイクルエンジンなので混合ガソリンを燃料に使う。ちょうど燃料切れになったのと同じタイミングだったので午前中の作業を終えた。11時の時点での田んぼの状況。

昼間は暑いので長くお昼休憩をとって14時から再開。本当はもう少し遅くてもよいけど、私が神戸に戻らないといけないから少し早めに始めた。まだ7月だったせいか、14時でも想像よりは暑くなくそれでよかったとも言える。午後から母がパートから戻ってきたのもあり、交代して休みを取りながら草刈りをして16時にはほぼ完了できた。この後、少し残っているところを母にやってもらって私は17時の高速バスで神戸に戻ってきた。

この時期の草刈りは、草刈り機を使うことそのものの疲労に加えて暑さでバテる。2人いて交代で草刈りすると、休んでいる時間を有効活用できて効率がよいことに気付いた。草刈り機のエンジンの回転数も全開にするよりも、少し弱めた方が振動量が減って、腕の負担も燃料消費も少なくなってよいことに気付いた。いままで全開で刈った方が早く刈れるのではないかと考えていたが、それは誤りだった。疲労度を下げて草刈り機を扱った方が休まずに長時間作業できる分、全体として作業を速くできることに気付いた。

この後、草を干して乾燥したら焼いて、トラクターで田んぼを耕す。それは9月の連休にする予定。

ストレッチ

今日の開脚幅は開始前154cmで、ストレッチ後158cmだった。あちこち筋肉痛やら腰が痛いやらでストレッチできるような状態でもなかった。ストレッチへ行ったときは暑さにやられて頭痛がひどかったんだけど、ストレッチしているうちに徐々によくなってましになった。暑さで頭痛がするのは血行が悪くなるからだそうだけど、ストレッチして血行がよくなるんだと推測する。腰の張りがひどくてストレッチしてもらって少し楽になった。田んぼ仕事の後にストレッチを受けられるのは疲労回復のためによかったと思う。

実家に帰る

1時に寝て7時に起きた。実家に帰ってお見舞い行ったり親戚訪問したりしてた。

お見舞い

午後から父のお見舞い。少し前まで直接面会できるようになっていた時期があったそうだけど、またコロナの感染状況が悪化したため、リモート面会に戻ったらしい。面会時間は20分。たまたま父はお風呂上がりの時間だったらしくてそれで疲れたのか、10分ほどしてそのまま眠ってしまった。もともと父は気管切開していて話せないので起きていても寝ていても面会でやることは変わらない。顔色がよいことは確認できたという感じ。

博士ちゃん

たまたま実家に帰っていたからテレビをみていたらおもしろかった。生物の標本や骨に関心のある小学6年生が、国立科学博物館の収蔵庫を見学するといった番組だった。著名な研究者の方々が案内しながら子どもに研究のおもしろさを知ってもらうような作りになっていたように思う。出演していた12歳の子どもが本当によく勉強していて詳しくて、この分野の研究が本当に好きなんだなという想いがみてとれてよかった。好きなことを突き詰めてやっているのをみると楽しくなる。

カンバンの弊害

0時に寝て8時に起きた。起きたら豪雨だった。梅雨明けが早かったから水不足の土地には恵みの雨だなとか思った。

「緊急対応」という種別

先週のリリースに際して発生した問題に「リリース時緊急対応」という種別が設けられた。当時、私はその種別を設けることそのものに否定的なコメントを発したのだけど、誰かがすでにその種別を作ってしまっていて、いくつかのチケットに設定されていたので成り行きで使うことになった。そして、もうリリースしてから1週間も経つのに未だに「緊急対応」というチケットがいくつも作られている。1週間も運用しているのに緊急もへったくれもないだろうと指摘して、明日から新しいスプリントが始めるので「緊急対応」という種別を付けるのはやめようと提案した。一般的な課題管理システムは緊急度と重要度の2つをもっているけど、backlog は優先度しかない。それでも優先度があるのだからそれを設定すればいいだけなのに優先度を使った運用をしていないのと、課題一覧をフィルターするのではなく、大半のメンバーがカンバンしか使えないといったスキル不足もあって、なくてもよい無駄な種別をまた増やしてしまった。

カンバンはシンプルな要件に使うならよいけど、一定以上の複雑さをもつ普通の会社の開発プロジェクトに使えるようなキャパシティをもっていない。それなら最初から使わない方がよいのではないかと考えるようになってきた。というのは、非開発者にとってカンバンは簡単に使い始められる分、そこからさらに高度な検索フィルターを使いこなすスキルアップを阻んでしまう。複雑な要件をカンバンで実現しようと考えてしまってバッドノウハウ的なアプローチをしていく。その典型例が「緊急対応」という種別作ればいいやんみたいな考え方。

クレジットカードの有効期限の更新

前に yj カードが paypay カードに置き換わったときに有効期限が更新されてクレジットカードの設定更新が必要になると書いてあった気がする。4月8日に paypay カードが届いたみたい。クレジットカードの引き落としタイミングのせいか、しばらくは有効期限が異なっていても paypay カード側で決済を許可していたのか、いずれにしても最近あちこちでクレジットカードの引き落としに失敗するという通知がくるようになった。気付いたら、クレジットカードによる セカンドハーベスト・ジャパン さんの寄付の引き落としも止まっていた。通常、有効期限前にクレジットカードが更新されることはないからサービス側で有効期限が近づいてきたときに更新依頼通知を送っているのだと推測する。寄付みたいなところは引き落とし失敗になると督促しないのかもしれない。もう1つ 国境なき医師団 さんにも寄付しているが、こっちは銀行口座からの引き落としだった。クレジットカードと銀行口座の違いとして有効期限の有無が違う。どちらもメリット・デメリットがあるからずっと払い続けるつもりなら銀行口座、自分が死んだ後にいずれ停止してほしいならクレジットカードを使った方がよいといった考え方もできると気付いた。

放置していたバグを直した

1時に寝て7時に起きた。寝ていて夜中に吐き気して眠れなくて上体を起こすしかなかった。たまにある 胃食道逆流症 のひどいやつ。

参議院選挙

普段は期日前投票で済ませるのだけど、今週は他のことに注意を取られていたせいか、当日行ってきた。場所が期日前と違ったので勝手がわからなかったけど、とくに混雑もしてなかったのですぐに完了できた。タイムラインを眺めると、私のタイムライン上では投票したと発言する人が増えてきたように思う。投票率が50%程度で半分ぐらいの人が投票していない状況に懸念をもつ人たちの可視化がされている。

ふと父の選挙はどうなるんだろう?と思って検索してみた。意思表示できない状態だと選挙はできないみたい。

選挙人本人が投票所に行き自らの意思で投票することが原則であることから、意思表示が困難である場合には投票することはできません。これは投票所の係員が選挙人の投票を補助する代理投票においても同様です。したがって、家族の方が本人に代わって投票することはできません。

神戸市 FAQ > 市政情報 > 選挙

70歳以上は傷病で選挙権を行使できない人たちもいるだろうから減るのかな?と、総務省の 年代別投票率 のグラフを確認してみた。直近だと、70歳以上が61.96, 60歳代が71.43、50歳代が62.96だった。60歳代と比べて減ってはいるけど、50歳代とそう変わらないのをみると、元気な人たちに選挙へ行こうと呼びかけるのは正しい気がした。

backlog-github-integration-action のバグ修正

運用してすぐにコミットメッセージ中にシングルクォートやダブルクォートが含まれると引数を正しくパースできなくてエラーになることがわかっていた。いま運用している環境の用途だと、それほど重要ではないので後回しにしているうちに面倒になって放置していた。晩ご飯を食べてからデバッグしていたら7時間ぐらいやってた。

bash 上の文字列の扱いと action.yml の inputs の args に引数渡しするときの振る舞いの勘違いもあって、issue の見た目以上に複雑な振る舞いをしていることがわかった。github actions 上のコンテキストに依存したくなかったため、github.event.commits の json をそのまま cli パラメーターとして渡している。bash 上の json 文字列と cli パラメーターとしての扱いが煩雑になるのでこのやり方は失敗だったかもしれない。ローカルでのテストもやりにくい。私はそのことをよく理解していたはずなのに github actoins 上のアンチパターンにはまってしまった。カスタムアクションのユーザーが簡単に使えるように cli パラメーターの設定を簡単にする意図で json 渡しにしたんだけど、エスケープの振る舞いが想像以上にややこしくなって、エスケープしたいユーザーには簡単ではなくなってしまった。それでもデバッグをがんばったおかげでシングルクォートは完全に使えるように実装できた。ダブルクォートは制限付きでエラーにならなくできるが、事実上は使わないでくださいといった仕様制限にしてしまおうと思う。引用するときはダブルクォートじゃなくてシングルクォートを使ってくださいと啓蒙することに決めた。

github actions の push イベントワークフロー改善

23時に寝て6時に起きた。今週はサービスインで凸凹していて疲れた。

ストレッチ

今日の開脚幅は開始前161cmで、ストレッチ後164cmだった。ちょっと数値がよくなった。一昨日の日本酒イベントで4時間ほど立ち呑みをしていた疲労で腰に張りが少しあった。それ以外はとくに問題はなくて調子がよかった。右股関節の詰まりも2-3週間前よりもよくなっている気がする。これはトレーナーさんも注意を払って詰まりを取り除くようにストレッチのメニューを組んでくれているのでその成果が徐々に出始めている気がする。以前よりも可動領域が広がってきている気がして安心感を得た。

github actions の push イベントワークフロー改善

午後からビルド・デプロイの最適化のために github actions のワークフローを改善作業をしていた。

今週はサービスインにより、本番環境への緊急リリースを何回もやっているのを傍からみていて、ビルド・デプロイが速くなればなるほど、その回数を増やせるし、修正後の検証に時間を多く割ける。あるリポジトリが7つのモジュールをまとめてビルド・デプロイしている。これはあるモジュールの微修正の反映には向かないので改善することにした。結果として最大で50%ぐらいのビルド時間の削減、モジュールに依っては、具体的には10分かかっていたものを4分台でビルドできるようにした。

ワークフロー改善のためのデバッグしている間はビルド・デプロイが出来なくなることから開発者が使っていない時間帯が望ましい。必然的にサービス休日出勤して github actions のワークフローを改善していた。デバッグと動作の検証も兼ねて午後から半日以上やっていたので休日にやったのは正解だと言えるだろう。

push イベントの github コンテキストの github.event.commits にコミット情報が入っていて、そこにコミットのリビジョンがある。例えば、次のようなオブジェクトで id がコミットのリビジョンに相当する。

[
  {
    "author": {
      "email": "...",
      "name": "...",
      "username": "t2y"
    },
    "committer": {
      "email": "...",
      "name": "...",
      "username": "t2y"
    },
    "distinct": true,
    "id": "f8df1f77ffec9ef234e7321b2e237b663256b01c",
    "message": "コミットログのメッセージ",
    "timestamp": "2022-07-08T12:32:33+09:00",
    "tree_id": "37b066734e58779c5d2c687d40b4cc43af177cb2",
    "url": "https://github.com/OWNER/REPO/commit/f8df1f77ffec9ef234e7321b2e237b663256b01c"
  },
  ...
]

このリビジョンを使って github rest api からファイル情報を取得できる。

$ gh api -H "Accept: application/vnd.github+json" /repos/OWNER/REPO/commits/f8df1f77ffec9ef234e7321b2e237b663256b01c

いろんなデータが返ってくるけど、ここでは変更したファイルのパスを知りたい。

{
  "sha": "...",
  "node_id": "...",
  "commit": {
    ...
  },
  ...
  "files": [
    {
      "sha": "...",
      "filename": "module1/path/to/src",
      ...
    },
    {
      "sha": "...",
      "filename": "module2/path/to/src",
      ...
    }
  ]
}

この filename のトップディレクトリがモジュール名と同じなのでここだけ取り出して、管理対象のモジュールかどうかを比較する。bash でも =~ をサブ文字列のマッチングができる。

$ targets=(mymodule1 mymodule2)
$ echo " ${targets[@]} "
 mymodule1 mymodule2 
$ [[ " ${targets[@]} " =~ " mymodule1 " ]] && echo "match"
match
$ [[ " ${targets[@]} " =~ " mymodule2 " ]] && echo "match"
match

さらにマッチしたモジュールを github actions の expressions で制御しやすいように json の array に変換する。

$ jq --compact-output --null-input '$ARGS.positional' --args -- ${targets[@]}
["mymodule1","mymodule2"]

これを step の outputs として格納する。

echo "::set-output name=modules::${json_array}"

例えば、後続の job で実行条件としてモジュールの有無を調べたいときは expressions を使って次のように記述できる。if 文は ${{ ... }} のブラケットを省略できるようだけど、ここだけ省略すると返って混乱するかなと思って私は記述するようにしている。その方が統合性があってコードが読みやすいように私は考えている。

  mymodule1-job:
    if: ${{ contains(fromJSON(needs.build.outputs.mymodule_target.modules), 'mymodule1') }}
    needs:
      - build

ちなみに workflow レベルの env は job の if 文には使えない。outputs を使って動的な値を扱うようにしている。どうも workflow レベルの env はいろいろ問題があるみたいでなかなか issue がクローズされないのをみると取り扱い注意なのかもしれない。

最終的なモジュールを判別するための step は次のようなものになった。

  build:
    outputs:
      mymodule_target: ${{ steps.mymodule-target.outputs.modules }}
    steps:
    - name: コミットログからビルド対象のモジュールを設定
      id: mymodule-target
      run: |
        declare -A modules
        target_modules=${{ env.TARGET_MODULES }}
        revisions=$(jq --raw-output '.[].id' <<< '${{ env.COMMITS }}')
        for revision in ${revisions}
        do
          names=$(gh api -H "${{ env.ACCEPT_HEADER }}" ${{ env.COMMITS_PATH }}/${revision} | jq --raw-output '.files[].filename' | cut -d"/" -f1 | sort -u)
          for name in $names
          do
            if [[ " ${target_modules[@]} " =~ " ${name} " ]]; then
              modules[${name}]=true
            fi
          done
        done
        targets=$(jq --compact-output --null-input '$ARGS.positional' --args -- "${!modules[@]}")
        echo "::set-output name=modules::${targets}"        
      env:
        TARGET_MODULES: |
          (
            'mymodule1'
            'mymodule2'
          )          
        ACCEPT_HEADER: "Accept: application/vnd.github+json"
        COMMITS_PATH: /repos/${{ github.repository }}/commits
        COMMITS: ${{ toJSON(github.event.commits) }}

処理も理屈も簡単なんだけど、実際の運用コードはもう少しだけ複雑なものの、デバッグは github actions を実行しないといけない。ちょっとした typo のために実は2時間ほどはまっていたのは内緒。シェルの配列や連想配列を使うと、記号が多くてわかりにくい。配列の閉じブラケットを忘れていたがために EOF のエラーが発生していた。閉じブラケットのミスだけにエラーが発生しているところと実際のコードがズレていて、それに気付くのに少しずつコードを足したり消したりしてデバッグするみたいな原始的なやり方で些細な typo を気付くのに時間がかかった。

xxx.sh: line 47: unexpected EOF while looking for matching `"'

夏休み

0時に寝て7時に起きたけど、昨日から体調よくなくてしんどくて寝てた。

開発やら決算の事務手続きやらのタスクが一段落して余裕時間ができたことでぼーっとしてた。まぁたまにはそういう日もあるか。何も作業せず休んだ日は day off というタグを付ける。あとで何日ぐらい休んだか、どのぐらいの期間で休んだかの確認にもなるかもしれない。

夏バテ

0時に寝て7時に起きた。途中で吐き気がして何度も起きた。夜うまく眠れない。

ストレッチ

今日の開脚幅は開始前160cmで、ストレッチ後163cmだった。先週とほぼ同じでよい状態を維持できている。外が暑くなってその比較から dr.stretch さんの事務所はエアコンがよくきいていて涼しい。うちのオフィスはエアコンの設定温度を上げる人がいて気付くと26.5℃とかに設定されていて私にとっては暑い。とくにどこか張りの強い部位や痛いところはなかった。夜にあまり眠れないわりには身体的には負荷がかかっているところはなさそう。

ストレッチを終えてからオフィスに戻って軽く調べものして、眠くなって仮眠して、そのまま家に帰って寝てた。とくに急ぎでやるタスクがなかったせいか、なんか一気にバテた。