YouTubeの広告ブロッカーブロッカーの研究

自由研究 としてYouTubeが広告ブロッカーを検知する仕組みを調べていた。有名な広告ブロッカーを狙い撃ちにしているのかと思いきや、僕が 研究用 に作った簡易的なブロッカーにもちゃんと反応していた。

https://www.youtube.com/s/player/5ae7d525/player_ias.vflset/ja_JP/base.js より抜粋

    g.E.onClick = function(k) {
        k && k.preventDefault();
        var p, t;
        dDL(k, {
            contentCpn: (t = (p = this.api.getVideoData(1)) == null ? void 0 : p.clientPlaybackNonce) != null ? t : ""
        }) === 0 ? this.api.zb("onAbnormalityDetected") : (SA.prototype.onClick.call(this, k),
        this.api.zb("onAdSkip"),
        this.api.onAdUxClicked(this.componentType, this.layoutId))
    }

クリックイベントkをdDLに渡し、その返り値が0ならonAbnormalityDetectedイベントが発行され、その結果広告ブロッカーやめろ画面に遷移する。

    dDL = function(k, p) {
        var t = 1;
        k.isTrusted === !1 && (t = 0);
        a3("ISDSTAT", t);
        qO(t, "i.s_", {
            triggerContext: "sk",
            metadata: p
        });
        return t
    }

dDLの実装を見るとisTrustedがfalseなら0が返る。
https://developer.mozilla.org/ja/docs/Web/API/Event/isTrusted

ユーザーを意図しない操作から守るためにブラウザが提供している機能なので、これを出し抜くのは結構難しい。相当な荒業でやる方法はあるようだが、addEventListenerが実行される前にinjectせねばならずなかなか難易度が高い。
https://qiita.com/i11u/items/0a6d38966c75314bacba

Chrome extensionのdeclarativeNetRequestを利用してbase.jsがダウンロードされるときに該当箇所を書き換えてしまえばいいのではと思ったのだが、preload+service workerが使われている影響かbase.jsのGETを捕捉できなかった。あとはプロキシサーバーを立ててbase.jsだけすり替えるとかできるのかなあ。なんならChromiumをforkしてisTrusted機能を殺してしまうのもありかもしれない。Chrome拡張という配布のしやすい形を諦めるなら選択肢はいろいろある。

あくまで 研究 ですからね。私欲のために実行しませんよ。こういう研究をしていると広告が流れてくれた方が都合がいいのだが、そう思っているときに限って意外なほどに流れない。こんなに頻度低かったかな…?と思ってしまい、それなら別にいいやとなってしまった。逆物欲センサー(だいぶ昔の言葉になってしまったな)。

webサービスをどう設計するかは作り手の自由だが、それと同時に我々が自分の所有する計算機でどのような計算を行うかも自由だ。つまりはそういうことだ。

こういう漠然とやりたいことはあるけどどうやるべきかもどう書くべきかもわからない状況、雑にCline+Claudeに書かせておいてよくわからないところはCopilotに説明させてあーそういう意味ねと納得したりしている。Clineが大きなスコープでの作業を得意とする一方でCopilotはインライン操作が充実していて細かい部分について質問しやすい作りになっている。LLMの特性と言うよりはプロダクトとUIの特性だね。

20250222 Cline+Claudeやってみた

昨日は国外出張から戻った友人の無事を祝って御徒町で飲んでいた。飲みはとても楽しかったのだが寒さと胃腸の弱さ(普段は全く自覚しないが飲み屋でだけ覿面に弱くなる)ゆえに酷い胃もたれを起こしてしまい、帰って苦しんで寝ていた。寝るタイミングを逃し、寝ないまま今日に突入。午前に用事を済ませ、昼はもつ煮屋で食べてきた。スタミナもつ煮ってなんだろう、大きいのかな?と思ったらニンニクモリモリで、なるほど写真じゃわからんかった!!となった。

mizchi氏の魂がまた震えているらしいのでとりあえず真似してCline+Claudeを導入してみた。Clineは任意のLLMのサポートを得ながらvscodeを自動操作するvscode拡張で、単なるコード生成を超えてシェルやpuppeteerまで操作して勝手に動作確認までやり始める。マジですごい。ClineのバックエンドになるLLMは幅広く選べるのだが、おすすめはClaudeらしい(ローカルollamaは遅すぎて無理だった。GitHub CopilotはVS Code LM APIという仕組みを通じて使えるのだが、トークンが激増するらしくすぐrate limitになった)。Claudeを使いたいときはClaudeに直接金を払ってもいいし、OpenRouterというサービスを使ってもいい。OpenRouterは様々な商用LLMを統一的なインターフェースでアクセスできるように集約したもので、ここにお金を入れておくと使ったLLMに使った分だけ支払われる。若干手数料は乗るのだが、AIアシスト開発はいろいろなモデルを試す段階だと思うので便利。Claudeとdeepseekを比べてみたけどやっぱりClaudeの方が強かった。

とりあえず20ドル入れていろいろ遊んでみたのだが、使い方によって課金額が結構違う。コンテキストをリセットしないまま長話をするとトークンが嵩んで高くつくようだ。その辺りに少し慣れた状態で、日々の日記のアレを生成するサービスを作らせてみた。20コミット1000行分くらいのちょっとしたもので3~4ドルくらいかな。Claudeとの1回の応答で0.02ドルくらい。

https://chao7150.github.io/discipline/

(以下はサンプルです)

項目 内容 得点
起床 7:30 100
散歩 実施・ゴミ拾いあり・犬0匹() 100
朝食 三色食品群のうち0色カバー 0
体操 実施 100
労働 passion: 0点, discipline: 0点() 0
ジム 有酸素+筋トレ 100
勉強会 実施 100
個人開発 実施 100
総合 1日の総合評価 59

Claudeはとても賢い。曖昧な自然言語で指示を出してもかなり正確に意図を読み取ってくれるという点で対人間インターフェースは非常に優秀。知識も豊富でライブラリの使い方とかもよく知っている。コードの整理・美学みたいなものは弱く、場当たり的な構造を作りがちに見える(まあ1つずつ指示を受けながら作っていくという条件なら人間でもそうなるかもね)。Claudeを活用してある程度まで野放図に成長してしまったアプリケーションに、後から人間の開発者が複雑な機能を追加するとなると辛いだろうな。

これ仕事で使えるようになったら俺の仕事何が残るんだろう。大きいアプリケーションを作ろうとなったらやっぱり人間エンジニアが整理しないと破綻するのかなあ。なんかそれも希望的観測のように思える。非エンジニアが直接プロンプトを叩いて(しかも何回細かい修正指示を出しても不満を言わない)かなりの精度のものが作れるだろうし、そんな時代にコードを美しく整理するということに意味があるんだろうか。衝撃的な体験だった。

リストのツールチップをgridで作る/ローカルLLM環境構築

リストのツールチップをgridで作る

リストの項目をクリックすることで詳細情報が展開されるタイプのUI(これツールチップって言うんか…?)。

  • その項目の近くに表示されてほしい
  • 詳細情報が表示されることでリストの配置が乱れてほしくない

という前提を置くと、position: absolteで配置するのがシンプルだろう。しかしabsoluteによる配置物はレスポンシブ化が難しい。詳細情報のwidthを固定すると画面の横幅が狭いとき小さくなってくれずにはみ出すし、逆に親であるリストに合わせて100%とするとリストの大きさを先に確定させる必要があり、リストの隣にも表示物があるので不都合だった。

いろいろ考慮した結果gridで詳細情報表示領域を確保してやるのがいい感じだった。まず4行のgridを作る(画像では5行あるがここでは関係ない目的で1つ多い。気にしないで)。詳細情報を表示する前の各項目は3行だけ利用する(grid-column: span 3;)。

■■■□
■■■□
■■■□
■■■□
■■■□

そしてある項目の詳細情報を表示するときは、HTMLでその項目の直後に1行n列(図ではn=3)の要素を置く(grid-column-start: 4; grid-row: span 3; 4行目に3列分使って要素を配置する)。


■■■□
■■■□
■■■▤ <選択
■■■▤
■■■▤

cssは本当に難しい。各要素の大きさがどこで決まっているのかわからない、ググったときに情報の質がピンキリ、プログラミングよりも1つの問題に対して様々な解決法があり良くない意味での創意工夫の余地が大きい。さらに個人開発で言うと終わりがない。いつまでも触れてしまう。僕はあまり考え過ぎたくなくてGoogle検索をひたすらパクるという方針でやっているのだが、Google検索のUIも少しずつ変化しているのでな…。

ローカルLLM環境構築

AI系の開発をやってみたいけどOpenAIに金払いたくないのでローカルマシンでLLMを動かすというのにチャレンジしていた。動かす事自体はそう難しくなくollama(LLM界のdocker cliみたいなやつ)を入れて、huggingface(LLM界のdockerhubみたいなやつ)からpullしてきてrunすれば済む。そこにwebuiをつけたりAPIアクセスしたりweb検索エンジンと連携させたり…みたいな細かい手間もあるが別にAIだから難しいということはない。

難しかったのは個人所有程度のマシンでLLMを動かしても速度も質も全然ダメというところだ。browser-useでURLを指定してこれを開けと指示するだけでもCPU100%で30分間かかってまだ終わらない。こういうのをやってみるとChatGPTがいかにものすごいか(LLMを実用レベルにするためにどれだけの半導体と電力をつぎ込んでいるのか)というのがわかる。

また今アツい分野であるだけに技術の進み方も速く、今日入れてみたパッケージが今日の更新で壊れてて3時間前にissueが立ってリアルタイムで解決法が共有されているという光景を目にした。不安定ではあるがダイナミックな活力がある(他分野から見るとwebフロントもこう見えるんだろうか、最近はさすがにすこし落ち着いていると思うが)。

ReactでdetailsをoutSideClickで閉じるやつ

自作のアニメ視聴管理webサービス watch-duty-manager にこのようなメニューUIがある。ハンバーガーを押すとメニューが開く。これはHTMLのdetails/summaryタグで実現している。

こういうメニューはメニューの外側をクリックすると閉じるのが一般的だ。しかしdetailsタグは標準でそのような挙動をしない(まあメニューにだけ使われるものではないからね)。summary(ハンバーガー部分)をもう一度押すことで閉じることができる。外側クリックで閉じる方法を適当にググってみると

  • detailsが開いているときはcssでsummaryを画面全体を覆うように巨大化させる
  • JavaScriptのクリックイベントを全て拾ってなんとかする

という2つの方針が見つかった。1はなかなか賢いと思うものの、真面目に作り込もうと思うとなかなかバギーな部分もありそうで(特にレイヤー順とか)やめて2をやることにした。

みんな大好き react-use に useClickAway というカスタムフックがある。refで参照されたHTML要素の外側がクリックされたときに指定されたコールバックを実行する。実装としては愚直に2をやっているだけ。

// https://github.com/streamich/react-use/blob/ad33f76dfff7ddb041a9ef74b80656a94affaa80/src/useClickAway.ts#L16-L22

const handler = (event) => {
  const { current: el } = ref;
  el && !el.contains(event.target) && savedCallback.current(event);
};
for (const eventName of events) {
  on(document, eventName, handler);
}

これを使って

function Component() {
  const ref = useRef<HTMLDetailsElement>(null);
  useClickAway(ref, () => {
    if (ref.current && ref.current.open) {
      ref.current.removeAttribute("open");
    }
  })
  return (
    <details ref={ref}>
      <summary>summary</summary>
      details
    </details>
  )
}

てな感じでやれば一応動くものは作れる。作れるのだが、この作りだとdocument内のどこをクリックしても、画面内のこのコンポーネントの数だけ ref.current && ref.current.open の評価が走る。実際のユースケースでは100個くらいの表示はあり得る。まあ実際のところ100個あろうと大したコストではなく、使用感に影響を与える16msには届かないのだが、個人開発だからそういう現実的な損得はおいといて、もっと効率的な作りを追求することにした。

この作りの何が無駄かと言えば同時に開くdetailsは1個しかないのに画面内のdetails全てに対して同じ判定関数を与えていることだ。そこでデフォルトではなにもしない関数を渡しておいて、detailsが開いたときだけuseClickAwayに渡す関数を差し替えることにした。

const noOpCallback = () => {};

const useCloseDetailsOnClickAway = () => {
  const ref = useRef<HTMLDetailsElement>(null);
  const closeCallback = useCallback(() => {
    if (ref.current) {
      ref.current.removeAttribute("open");
    }
  }, [ref.current]);
  const [onClickAway, setOnClickAway] = useState({ f: noOpCallback });
  const onToggle = useCallback<React.ReactEventHandler<HTMLDetailsElement>>(
    (_) => {
      if (ref.current === null) {
        return;
      }
      if (ref.current.open) {
        setOnClickAway({ f: closeCallback });
      } else {
        setOnClickAway({ f: noOpCallback });
      }
    },
    [],
  );
  useClickAway(ref, onClickAway.f);
  return { ref, onToggle };
};

function Component() {
  const { ref, onToggle } = useCloseDetailsOnClickAway();
  return (
    <details ref={ref} onToggle={onToggle}>
      <summary>summary</summary>
      details
    </details>
  )
}

その結果できたカスタムフックがこれだ。detailsのtoggleイベントを監視して、開いたものだけuseClickAwayのコールバック関数をcloseCallbackに差し替えている。

ちなみに数字上の速度差はなかったです。たぶんReactやV8がなんとかしてるんでしょ。

 

20250105 作らされたいもの/RimWorld終盤の資産管理と人生訓

作らされたいもの

作りたいものねぇ〜とか言っていたら昔作ったwebアプリケーションをまだ使ってくれている友人から機能の要望が来て、若干の修正と膨大なリファクタリングが発生していて楽しい。しかし連休の終盤に楽しくて夜ふかししているのは頭が悪い。

昔作ったものだから結局コンフォートゾーンに逆戻りしているということではあるんだけど…まあ何もしないよりはマシかな。TypeScript+prismaでデータベースを複雑にいじくるところで(mysqlだとcreateManyAndReturnが使えません)、fp-tsで型をガチガチに固めているので絶対間違ったプログラムを書けないのだが、だからと言って正しいプログラムが書けるというわけでもなく苦労している。fp-tsの型エラーは原因箇所と遠く離れた場所に出るので何を間違ったのか探すのにコツがいる。好きな思想のライブラリではあるんだけどやっぱり言語機能の支援なしにこういうことをやろうとするとどこかに無理が生じるのよね…。

本日

今日からジムが開いていたので行って全身シバいてきた。少し衰えていたが想定内だ。NHKラジオニュースではUSスチールの買収差し止めが大きく扱われていた。大変だ。昼は久々に餃子の王将に行ってみたが、日高屋よりは美味しいだろうと期待しすぎた結果思ったほどじゃないな…となった。かぼちゃを買って帰宅。

RimWorld終盤の資産管理と人生訓

RimWorldは佳境である。いよいよ宇宙船の研究が一通り完了し、後は地道にウランやらプラスチールやら先進コンポーネントやらをかき集める段階に入った。ここの進め方がなかなか難しい。コロニー経営は軌道に乗っていて金も食料も有り余っているのだが、希少資源はそうそう見つからないので金余りの状態になりやすく、そのせいでゲームシステムによって敵の襲撃が強力になってしまう。かと言って金を捨てるといざ希少資源が見つかったときに買えない。つまりゲームシステムにバレない場所に資金を移動させる必要があるのだ。

一つの方法としてはキャラバンに乗せて適当な人員にコロニー外を徘徊させるというのがある。物理的な資産隠しだ。しかしこれはあまりにもゲームを騙してる感が強くポリシーに反するのでダメ。他の方法としては近隣の他勢力に配っちゃうというのがある。もちろんその資金は消滅するのだが、その分友好度が上昇し、いざというときに助けに来てくれたりキャラバンを派遣してくれたりする。

人を働かせて金を集めるシステムを構築したら次はその金を隠したり配ったりというのは嫌なリアリティがあるが、溜め込むくらいなら人に配ってしまえというのはなかなかポジティブな人生訓ではないだろうか。資産を持つことはそれ自体がリスクである。価値は損耗・変動するし、奪われる可能性もある(現代日本の銀行だって1000万円までしか保証してくれないぞ)。それに対して、ロマンティックに言えば友情、システマティックに言えば互恵性の規範に投資するという道もあるぞということをこのゲームは提示しているのだ(厳密に考えると金銭投げつけは友情なのか?という疑問は新たに浮かんでくるが…)。

ちなみに住人の一人であるElk(39歳独身男性・社交能力1)は性欲が強すぎて人妻を含む周囲の女性に声をかけまくり、当然のごとく振られ続けた結果メンタルを悪化させ暴れだしたので逮捕・収監と相成りました。そのうち復帰はさせようと思うけどもう女性と顔を合わせないように深夜シフト固定かなあ。これはネガティブな人生訓。

ソフトウェアエンジニアリングチームはオーケストラか

専門的な技能を持った個人の集団がコミュニケーションを取りながら成果物を完成させるという点で、ソフトウェアエンジニアリングチームはオーケストラに似ている。長い期間に渡って同じシステムを育て続けるチームを想定している。

似ていること

  • 一人ひとりの能力の総和が単純にチームの能力にならない。良いコミュニケーションと良い文化・伝統が必要。
    • 一人のスーパースターの存在は、ある程度成果物の質に効いてくるが、決定的ではない。トランペットだけ超うまいオーケストラはトランペットパートで見せ場を作れはするが、それが他の弱点を覆い隠せるわけではない。スーパーエンジニアはアーキテクチャを設計できるが、同時にチームを教育し浸透させないと少しずつアーキテクチャの意図からズレたコピペが横行し、破綻する。
    • 技術的なボトルネックの解決とかは一人で大きく貢献できるかもしれない

違うこと

  • ソースコードは有形で永続化されている。いつ誰がどのような判断でその一行を書いたのか、高い確率で検証することができる。
    • オーケストラも楽譜に歴史が刻まれているとは言える。オーケストラは楽譜を所有しており、過去にやった曲であれば当時の書き込みが残った状態で使う。指揮者が変わって演奏指示が変わったりした場合は書き込みが更新される。しかしgitのように履歴を追跡できるわけではない。
  • コードを全く触らなくてもある程度の期間は動かし続けることができる
  • 新人をカバーし教育をすることができる。オーケストラでは一人音程が違えばバレてしまうが、ソフトウェアエンジニアリングではプルリクエストとレビューを通してカバーすることができる。
    • リアルタイム性の違い
    • しかし負担は大きい。『人月の神話』で論じられているように、新人の教育役として作業から離脱する人間が出るので人員追加の採算が取れるまでの時間が長い。

特にここから何かを主張したいというわけではない。それほど考えを深めているわけではない。しかしオーケストラの組織運営は何百年という歴史の中で洗練されてきたので、ソフトウェアエンジニアリングチームもそこからなにか学ぶことが、できたりできなかったりするかもしれない?

  • 全体の方向性を指示し、ときにはマイクロマネジメントを行う指揮者(ただしそれらの指示は全て全団員が聴いている)
    • 桜井政博氏も組織論の動画でディレクターの指示は誰でも自由に聞ける場でやるって言ってた
  • 全体に対してより具体性の高い指示を出すコンサートマスター
  • 同一の演奏機能を有する奏者が1つのパートを構成する(レイヤードアーキテクチャ+コンウェイの法則?)が、その中でも1st, 2ndのような役割分担がある
  • パート内ではパートリーダーに合わせる
  • パートリーダーは必要に応じて他パートと調整を行う

こう、風呂で思いついたときにアイデアとしては面白いと思うんだけど、文章に纏めてみると大した内容じゃないなってやつ、あるある。

Ubuntu23.10に上げたときの作業記録

私物のUbuntuは定期的に(だいたい年に2,3回)OSの再インストールをしている。このくらいの頻度でやっていると再インストール後の作業にも慣れてくる。手元にメモはあるが、一応インターネットにも載せておこう。

前提

  • インストールするのは純正のUbuntu
    • 日本語Remixではない
    • 普段はLTSしか使わないが今回はpipewireを今すぐ使いたかったので特別に23.10
    • 経験的にLTSとそれ以外の安定性にはかなりの差があるので、よほどの理由がない限りはLTSを使うべき
  • ルートはNVMe SSD
  • ホームディレクトリ下の以下はHDD上の同名のディレクトリへのシンボリックリンクにしてある
    • Documents
    • Downloads
    • Music
    • Pictures
    • Public
    • Templates
    • Videos
    • workspace
      • 個人開発のコードが置いてある
    • .ssh
  • なので、持ち越したいデータは全部HDDに置いているのでNVMe SSDはUbuntu Installerで全消ししている

再インストール作業

  • USBメモリにISOを焼いてUEFIの起動メニューからそちらを起動
  • Default Installation(全部入りではないほう)
    • サードパーティソフトウェアは入れる
    • メディアフォーマットサポートも入れる
  • NVMe SSDを完全に上書きする設定
    • LVM, ZFS, 暗号化はしない
  • パスワードはpasswordとしておいて後で変更する
    • インストールウィザード中に記号を含んだ複雑なパスワードを設定すると、なぜか正確に記録されず、後で同じパスワードを入力してもログインできない

セットアップ作業

  • ディスプレイの並びを物理空間と一致させる
  • 4KディスプレイをWQHDに設定しなおす
  • アクセシビリティから「大きな文字」を有効化、カーソルを最大に
  • ホームディレクトリ上のディレクトリ名を英語にする
    LANG=C xdg-user-dirs-gtk-update
  • 「ディスク」からHDDを ~/storage にマウントする
  • 前述のホームディレクトリ上のディレクトリをstorage下へのシンボリックリンクにする
    ln -s ~/storage/Documents/ ~/Documents
  • firefoxからvivaldiを入れる
  • vivaldiの拡張機能としてbitwardenを入れる
  • vivaldiの設定をsync機能で復旧する
    • syncにはID/パスワードとは別に復号パスワードも必要なのでそれもbitwardeに覚えさせておく
  • フォントをtakao系に戻す
    sudo apt install 'fonts-takao-*'
  • vscode入れる
  • steam入れる
  • 日本語変換をできるようにする
    sudo apt install fcitx5-mozc
    im-config # fcitx5を選択
    fcitx5-configtool # 変換・無変換をそれぞれ入力メソッドオン・オフに割り当てる
    再起動
  • nerdctl入れる
  • vim入れる
  • git入れる
    • ユーザー名・メールアドレス・デフォルトエディタ
  • thunderbird入れる
    • メールアカウントの登録。YahooはIMAPとPOPを選べるがIMAP

あとは必要になってから

  • 各種プログラミング言語処理系

Q. 今回はなんでUbuntu23.10にしたの?

A. https://github.com/edisionnano/Screenshare-with-audio-on-Discord-with-Linux にpipewireが必須だったから(そして22.04のpulseaudioを止めてpipewireを入れたらなぜか日本語変換が壊れるという大事故が起きたから)

実際にやってみたところ音質が悪かったのでこれを使うのはやめたが、pipewireに移行したことによってbluetoothヘッドホンの扱いがよくなり、これまで何故か使えなかったHSP接続が可能になり完全に死に機能だったヘッドホンのマイクが使えるようになった。まあこれも音質悪いからあまり使う気ないけど…

あとはPC内での音声入出力の繋がり方が、pavucontrolでは見づらかったが、 https://github.com/Ax9D/pw-viz を使って視覚化できるようになった。

Q. LTSじゃないけど大丈夫?

OBSのソースに画像ファイルを選択するとき、ファイル選択ダイアログを開くと非常に重くなる。なんで?

AWS SAAを取った

合格。853点なのである程度余裕を持っての合格と言えそう。

インプット

AWSの知識はゼロスタートではなかった。使った教材はudemyのこれ。先に取得していた友人に勧められたので。

https://www.udemy.com/course/aws-associate/

1ヶ月前から1日あたり70分相当くらい見ていった。ハンズオンは全部見るだけにした。教材の質は結構良いと思う。日本語がおかしいとか、AWSのドキュメントのコピペだとか、重要な単語をずっと言い間違えてるとかそういうミスはある。でもそもそもAWSのドキュメントの日本語訳は読みにくいので、それを理解可能な日本語で整理してくれている時点でかなりありがたい。力作。

ハンズオンの割合が多いのだが、実際に画面を見ることで概念間の関係の理解が深まるということも多々あったので、試験対策として意義はあると思う(効率はまた別の話だが)し、それ以上に実務にも役立ちそう。

試験対策

練習問題としては、公式問題集の20問、なんかネットに落ちてるサンプル公式問題10問、udemyの各章の小テスト、udemyの模擬試験1(簡単)、udemyの模擬試験2,3(そこそこ)を解いた。全ての問題について、全ての選択肢がなぜ正解/不正解なのか復習した。

公式問題の20問

スキルビルダーの中でできるやつ。本番より少し簡単だった印象。最初にこれをやったので「重箱の隅をつつくような問題はでないんだな」と油断した。

udemyの各章の小テスト

重箱の隅をつつくような悪問だと思っていたが、実際このレベルの知識がないと解けない問題もある(捨てても合格はできるかもしれない)。

udemyの模擬試験

1は簡単。2はそこそこ簡単に思えたが70%で合格ライン以下だった。2を復習した後の3は難しく思えたが86%で合格圏内だった。問題の形式に慣れることが結構点数に影響するのだなと思った。詳細は以下。終わってみればどの模擬試験も本番より少し簡単だった。

たぶん問題はudemy側もAWS側も随時入れ替わるので、未来にこれを読む人はあまり信用しないでください。

非本質的な試験戦略

AWSの知識は当然ベースとして大事なのだが、4つの選択肢の中から間違っているものを3つ落とせればいいのだから、選択肢間の同じ部分と違う部分を見つけ出すという戦略に慣れることが必要だった。長い選択肢は一見すると難しそうに見えるが、他の選択肢と同じ部分は読む必要がない。

本番

思ったよりも幅広いサービスの、細かいところまで問われていて焦った。しかし冷静に選択肢を読んでみると必ずしも完全な知識がなくても解ける/絞り込める問題も多かったので、焦ってはいけない。点数に含まれない調整中の問題も含まれると知っていたので、難しい問題に対しては「これは採点対象外だろ〜」と思い込むことにした(あと各問の点数も難易度に応じて調整されるらしい)。

自信がない問題にはチェックを付けながら進め、65問解き終わったときに残り30分くらい。そこからチェック付きの問題20問を一通り確認して残り10分、後は最初から順に見直して真ん中あたりでタイムアップ。試験終了時まで自信がなかった問題は12問だった。

英語の試験問題の日本語訳は概ね問題ないのだが、英語を見ないと間違える問題や、英語を見ることで自分が日本語を誤読していたことに気づいた問題もあった。怪しい問題については英語に切り替えて確認するのも有効だと思う。日本語訳を見てからなら英語問題を読むのは難しくない。

あと、これは友人にも言われていたが、フォントが汚い。

試験のあれこれ

自宅の環境を整えるのが面倒だったので試験センターを予約した。早めに着いたら早めに受けられたが、逆に試験センターで勉強しながら待つということはできなかった。

試験が終わったのは16時頃で、その日の18時頃には結果が出た。思っていたよりも早かった。嬉しかったので飲酒して帰った。

ヴァイオリンで小指を傷めた

今日も土曜日のルーティンを完遂でき、気分が良い。

ゴミ捨て

いつものスポットに捨てた。

水泳

いつも通り2ビートクロールで1km。SWOLFは70。少し効率的な泳ぎができるようになってきた。大昔は自分のへそを見るように頭を入れて泳げと習ったが、今日は真下を向いて泳いでみた。2ビートクロールの場合少し体をロールさせながらの方が推進力が入りやすい気がする。

インドカレー

なんとなくチーズナンが食べたい気分だったのでインドカレー屋に行った。セットメニューのチーズナン変更は差額ではなく満額必要と言われたが、食べたいものは食べたいので払って食べた。冷静にチーズナンじゃなくて良かったなと思った。

ヴァイオリン

カラオケボックスで1時間ヴァイオリンを弾いた。1時間弾いてようやく鳴りも音程も準備が整ったなという感じなので、本当は1日2~3時間は弾いてないと上達はしないんだろうなあ。

屋内で弾くと弓が吸い付くような感覚がある。これは逆に普段屋外で弾くときに風に煽られて弓が暴れる感覚に慣れてしまっているからだろう。そうなると弓をコントロールするために力が必要になり、脱力した正しい弾き方ができなくなってしまうのだが、仕方がない。「悪い癖がつくから弾かない」というわけにはいかない。

数日前はヴァイオリンで小指を痛めていた。フォームを変更してから1の指の使い方はかなりスムーズになったのだが、それと引き換えに小指が届きにくくなり無理な伸ばし方が必要になっている。親指の位置を調整することでもうちょっと良くなるかな。

買い物

卵とバナナを買った。卵は6個入りを買ってゆで卵にしている。食べやすくてタンパク質の補給になる。バナナはなんか今日売ってるのはどれも小さかった。

口座の整理

資産は2つの銀行口座と投資信託に分けているのだが、その移動をサボっていたのでやった。

ふるさと納税

例年年末に慌てるので今年は早めに。例年全額出身地だったが、今年は福島が大変そうなので少しそちらにも寄付してみた。寄付先の自治体が増えると手続きが面倒になる。いやそもそもこの制度自体が面倒を引き受けて小金を稼ぐしょうもない制度なのだが…

最近見た動画

モーツァルト『協奏交響曲』

ヴァイオリンとヴィオラがソロパートを弾く珍しい形の協奏曲。多くの場合ヴァイオリンの方が音が高く目立ってしまうのだが、この演奏ではヴィオラソロのティモシー・リダウトがモーツァルトにしては激しい演奏を繰り出し、ヴァイオリンに負けない存在感を放っている。たぶん録音もいい仕事をしているのだろう。彼の楽器は1570年頃に作られたそうで、今日高く評価されているストラディヴァリウスが1710年ごろであることを考えると、それよりも100年以上古い。古いということは技術もまだ進んでいなかったということで、それでも現在これだけ鳴るというのはすごいことだと思う。

『世界の果てに、ひろゆき置いてきた』

YouTubeの切り抜きしか見てないのだが、これはだいぶ面白い。普段の彼のネットでの振る舞いは嫌いなのだが、異国でのトラブルにも動じず飄々としている彼を見るのは軽快な編集と相まって痛快だ。やはりインターネットというのは悪なのだなと気付かされる。

そう考えてみると、普段のネット上でのひろゆきを称賛している人々には、彼がふっかける喧嘩がアフリカで出会うトラブルと同じように見えているのかもしれない。

最近読んでいる本

『プログラミング言語の基礎概念』は読み終わったことにした。証明とか、最後の方のクロージャの概念は完全には理解していないのだが、これ以上粘っても得るものがなさそうだった。

次はAWSの資格の勉強をする。Associateチャレンジキャンペーンで10月中の受験まで半額になる。

https://pages.awscloud.com/jp-traincert-certification-challenge-associate-2023-reg.html

Dota2

最近びっくりするくらい負け続けている。7.32の勝率が49%だったのに対して、7.33では41%、7.34では36%。レーティング制の5vs5のゲームで勝率36%ってすごくないですか?

自分のプレイが現在のバージョンの何かと噛み合ってないのだろうが、自分にはそれがわからない。外界とのインタラクションを意識しながら自分の行動を変えるのは苦手だ。さらにDota2ほど複雑なゲームになるとどの部分が悪かったのかわからないので困ってしまう。

Raspberry Pi Zero WHでNASしたい、失敗録1

配線

私はRaspberry Pi Zero WHを所有していて、これまで自宅の室温を記録してサーバーに送信していた。突然NASを組みたくなり、これを利用できないかと考えた。

ざっくりラズパイにストレージが接続さえできればあとはどうにでもなりそうだったので、アダプター類を購入して準備した。具体的には、Zero WHはUSB micro-B凹端子しかないので、ここから

  • USB micro-B凸 to USB A凹 変換
  • USB A凸 to USB A凹 ハブ(給電機能つき)
  • USB A凸 to SATA

の3段階を経てタンスに打ち捨てられていたHDDに接続。つないでlsblkするだけで認識できた。

HDDの準備

母艦側PCでHDDの中身を適当にサルベージしたあと、フォーマットしてLUKS暗号化しつつBtrfsでパーティションを作成。このあたりは全部UbuntuのdiskユーティリティでGUI操作可能だった。ただしGUI上でBtrfsを選択するためにはaptでbtrfs-progsを入れておく必要がある。

Raspberry Piのソフトウェアレイヤーの準備

よくあるチュートリアルのようにOpenMediaVaultを入れようとしたのだが、そのためにはRaspberry PiのOSがGUIをサポートしないバージョンでなければならない。そのために面倒な思いをしてOSを入れ直した。しかし改めてOMVを入れようとしたが、一般的なインストールスクリプトはRaspberry Pi Zeroには対応してないらしい。

RPi revision code :: 9000c1
This RPi1 is not supported (not true armhf).  Exiting...

仕方なくsambaに方針転換してインストールしてみた。

HDDをマウントする

LUKSで暗号化されたストレージは先に

sudo cryptsetup luksOpen /dev/sda storage

する必要があるのだが、なんとこれを実行するメモリが足りなかった(そんなことある!?)

Not enough available memory to open a keyslot.

ので、HDDを再フォーマットしてチャレンジします…