ただの時報
https://play-morse.lowreal.net/jiho.html
むかーーし作った時報のコードを発掘した。今なら Voicevox つけたらちゃんと喋る時報にできるぞと思ったのでガっとやった。正午だけ特殊なのでレアです。
短波JJYの再現
https://play-morse.lowreal.net/vhf-jjy.html
VHF JJYの再現スクリプトのほうも時報音声を入れるようにした。こっちは10分ごとにしか喋らないのでレアです。
https://play-morse.lowreal.net/jiho.html
むかーーし作った時報のコードを発掘した。今なら Voicevox つけたらちゃんと喋る時報にできるぞと思ったのでガっとやった。正午だけ特殊なのでレアです。
https://play-morse.lowreal.net/vhf-jjy.html
VHF JJYの再現スクリプトのほうも時報音声を入れるようにした。こっちは10分ごとにしか喋らないのでレアです。
Wikipedia の LDPC の項だけ読むとそんな難しくなさそうに見えるけど、実際に実装しようと思うと、むちゃくちゃ難しい。
LDPC符号の設計では、性能に優れたパリティ検査行列(H行列)を用意するのがまず難しい。ここにいろんな要素がある。
数学的素養がないと難しすぎる。そして自力で設計するのは考えたくない。
そんなH行列、例え1つ設計できたとしても、任意のデータ長・符号化率を持つH行列をいくつも作ろうと思うと何倍も大変になってしまう。
そこで Protograph (原始グラフ) という性質の良い原型となるような小さなグラフをまず設計し、それを何らかの方法で拡大して任意の大きさのH行列を得るという設計方法がある。
パンクチャリングは性質の良いH行列を使うために,多少の計算効率を犠牲にしつつ柔軟な送信ビット長/符号化率を得るための方法といえる
良い性質の Protograph を得られたとしても、それを拡大するプロセスには制約がある。整数倍の行列しか作れないとか。
そうなると求めるデータ長・符号化率ぴったりの行列というのは結局作れない。
これを解決するのがパンクチャリング。符号化率の低い(0.4など)のProtographを拡大し、欲しい符号化率 (0.5など)になるまでパリティビットの一部を送信しないことで、ちょうどいいサイズを作れる。
ぴったりよりも大きい行列を使うので計算コストは増えるが、高性能なH行列設計を流用できるという利点がある。
エンコードは既知の操作するだけやろ? という気持ちを打ち砕く。どっちも難しい。なんならデコードのほうが簡単かもしれない
performance.now() が monotonic (単調増加) なことを利用すると、システム時計の変化を比較的高精度に得られるなと思ったので、以下のようなClockMonitorクラスを作ってみた。
// ClockMonitor: システム時計の大幅な変更(NTP補正・手動変更等)を検知し、イベントを発行するクラス
// WebAudioやperformance.now()はmonotonicな経過時間だが、絶対時刻(Date.now())はシステム時計依存でジャンプすることがある
// そのため、performance.timeOrigin+performance.now()で絶対時刻を計算している場合、
// システム時計が変化しても自動で補正されない(ズレたままになる)
// このクラスは、定期的にDate.now()とperformance.timeOrigin+performance.now()の差分を監視し、
// 一定以上の差分が発生した場合に"clockchange"イベントを発行することで、
// 利用側がoffset等を補正できるようにする
class ClockMonitor extends EventTarget {
constructor({ threshold = 2000, interval = 1000 } = {}) {
super();
this.threshold = threshold; // 何ms以上の差分で検知するか
this.interval = interval; // 監視間隔(ms)
this.offset = performance.timeOrigin || 0; // performance.now()の起点(初期化時の絶対時刻)
this._timer = null;
}
start() {
if (this._timer) return;
this._timer = setInterval(() => {
const perfNow = performance.now();
const now = Date.now();
// 現在の絶対時刻の期待値(初期offset+経過時間)
const expected = this.offset + perfNow;
const diff = now - expected;
// threshold以上の差分が出たらシステム時計変更とみなす
if (Math.abs(diff) > this.threshold) {
// offsetを補正し、イベント発行
this.offset += diff;
this.dispatchEvent(new CustomEvent("clockchange", {
detail: { offset: this.offset, diff }
}));
}
}, this.interval);
}
stop() {
if (this._timer) {
clearInterval(this._timer);
this._timer = null;
}
}
} Date.now() を単に保持しておいて比較することでも、過去への遡りは検出できる。が、未来へ進むのは検出できない (ただのタイマーの遅れと区別できない)
問題点: performance.now() は monotonic ではあるがスリープで時間の連続性が失われることがある。
仕様上は連続することになっているが、一部の環境のブラウザだけ。
micro-template.js という2012年に作った embed JS 的なテンプレート処理ライブラリがある。コピペできるぐらい小さくて、早いことがコンセプト。
完全に放置してたけど、ちょっと手を入れはじめたらいろいろやりたくなってしまったので、だいぶ改修をいれてしまった。
いきなりトランスパイルの環境作って常時ビルドツールを動かして開発するのがいまいち性にあわず、いまだにそういうことをしないようにしてる。小さいプロジェクトだと管理が面倒くさい。
Vue3 はなんかいろいろさらに面倒になっており、公式のクイックスタートが全然クイックじゃねーよと思っていた。さらにクイックな方法を試行錯誤してたけど、現状の最小限サンプルを作っておくことにした。追記: 公式にも最小限サンプルあるわ……
最近のブラウザは ESM の import に対応しており、これ前提なら変なこと(ビルド)しなくても、このままに動く。ただブラウザで開くだけで良い。開発開始には十分だし、余計なことを考える必要はない。
一応ファイルを分けてるけど、app.js の内容は index.html に埋めこんでも良い。
「バニラJSだと面倒くさいUI状態があるが、いっぱいビルドとかはしたくない」みたいなことは多い。
以下は template 要素を使っている。template 要素を div 要素にして createApp に template を指定しなくても、mount("#app") でもいける。けど、template じゃない場合、table の td tr などで要素が消滅してハマることがある。
// app.js
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
createApp({
data() {
return {
counter: 0,
}
},
mounted() {
console.log('App mounted');
},
template: document.querySelector('#app').innerHTML
}).mount(document.body); <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script type="module" src="./app.js" defer></script>
</head>
<body>
<template id="app">
<h1>Hello</h1>
<button @click="counter++">Click me</button>
<p>Counter: {{ counter }}</p>
</template>
</body>
</html> petite-vue はメンテされてるのだろうか。どこかのタイミングでVue3の機能やらビルドをしたくなったときのことを考えると Vue3 そのまま使ってもいいと思う。
音価を維持して和音をペーストする MuseScore のプラグイン を書いてみた。(Claude Codeが書いた)
ギターの譜面を作ろうと思うと同じリズムでコードだけ違うのをいっぱい入力する必要がでてくる。MuseScore 標準だとコピペがかなり不自由で嫌気がさしていた。普通に考えて、コピーしているものをペースト先の音価を維持して置き換える機能があっていいと思うんだけど (もしかしてある?)
プラグインを起動するとコピーとペーストのボタンが出るので、コピー元の和音を1つ選択してコピーボタンを押し、ペーストしたい先の範囲を指定してペーストボタンを押す。すると音価は維持されたまま、指定した範囲の和音が置き換わる。
久しぶり VPS の top を眺めていたら systemd-journald が9%食っていることに気付いた。2GB のマシンなのに。
どうやら SystemMaxFileSize を小さくするとメモリ消費量も減るらしい。ので以下のように設定した。
[Journal] SystemMaxFileSize=32M SystemMaxFiles=100
systemctl restart systemd-journald
/var/log/journal はあり、こちらでディスクを 4GB ほど消費している。
$ ls -altrh /var/log/journal/*/ -rw-r-----+ 1 root systemd-journal 128M Apr 29 13:41 'system@...68e.journal' ...
1ファイルあたり128MBが32個ほどあった。SystemMaxUse のデフォルト値はややこしいので man 確認する必要がある。自分の環境の場合、ディスクが48GBで、デフォルトの最大は10%の4.8GB、ただし 4GB が上限。
ファイルの数 (SystemMaxFileSize) は SystemMaxUse の 1/8 らしいので過去ログは7件しかないはずだけど、なんかいっぱいあって謎。しらべてもよく挙動がわからんかった
Text-Xatena というはてな記法に近い記法をパースしてフォーマットする Perl のモジュールがある (ややこしい言いかただが……)。この日記も Text-Xatena + 拡張インライン記法でフォーマットされている。
golang にも同様のものが欲しくなったので作ってみることにした。
一応もとの Text-Xatena 同様、HatenaCompatible モードというのをつけてある
https://cho45.github.io/xatena-go/
golang は wasm に直接出力できるので、これでデモページを作ってみた。.wasm ファイルが 6MB超あるけど……
Text-Xatena のほぼ単純移植として実装する方針で、Copilot (GPT 4.1) と共にやってみたけどまぁまぁ面倒だった。
元実装があり、あまりデザインを変えずに言語を変更するという感じなので、AIでもできるだろと思ったけど、案外うまくいかず、結構いちいち指示やら手を入れることが必要になってしまった。とはいえ自分で書くよりは早くできたと思う。
ある程度できてくれば複数ファイルにまたがる変更もやってくれるけど、微妙に修正漏れがあったりして面倒。
テストの雛形をつくったあと、Perl のテストファイルをコピペして、それぞれ分けてテストファイルつくるように指示したけど、テストの中身を適当に書きかえられてひどかった。
コンテキストを小さくするために、先に全体の要約とか実装方針とかをまとめたほうがよかったのかも…… 自分は元コードを理解してるから、元コードの要約をさせる発想がなかったのが敗因かもしれない。
IT技術者なのに情報処理系の試験はまったく受けずに生きてきてしまった。アマチュア無線技士や第二種電気工事士とは違って法的に別にできることが増えるわけではなく特に受けるモチベがなかったからだけど、諸事情によりITパスポート試験は受けてみることにした。
毎週試験が受けれるみたい。過去問を1週間で1450問ほど解いた。
出題範囲が広い割に問題数は100しかないから、問題運で結構ブレそう。結果はテクノロジがストラテジより低くなってしまった。個別の正誤判定はないから何ミスったかはわからない。
なんかよく意図がわからない問題があった。あとは普通に知らない言葉の意味を聞かれる問題があった。ので、そのあたりを順当に間違えてそう……
定義が問題文に書いてある(ほぼ無知識で回答できる)やつと、聞かれてるものはわからないけど消去法で1択のものを落とさないように気をつけた。知ってないと答えようがない問題はあきらめた……
自宅ラズパイのメトリクスとかセンサー類を VPS 上の prometheus に溜めているけど、1年分で12GBぐらいと、用途の割にかなり大きくて、容量が足りなくなったときに悩んでいた。
VictoriaMetrics だと圧縮効率がよいらしいので試しに移行してみた。クエリ (MetricsQL) は PromQL 互換らしい。事前に調べたけどあんまりデメリットがなさそうに思えた。クラッシュなどによる多少の損失を許容しているところぐらい? 自宅のあれこれでは問題ない要件
sudo mkdir -p /usr/lib/victoriametrics/bin sudo mkdir -p /etc/victoriametrics/vmagent sudo mkdir -p /var/lib/victoriametrics
sudo useradd -s /usr/sbin/nologin victoriametrics
sudo chown -R victoriametrics:victoriametrics /var/lib/victoriametrics
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.117.1/victoria-metrics-linux-amd64-v1.117.1.tar.gz
tar -xzf victoria-metrics-linux-amd64-*.tar.gz
sudo cp victoria-metrics-prod /usr/lib/victoriametrics/bin/ wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.117.1/vmutils-linux-amd64-v1.117.1.tar.gz tar xzvf vmutils-linux-amd64-*.tar.gz sudo cp vmagent-prod /usr/lib/victoriametrics/bin/ sudo cp /etc/prometheus/prometheus.yml /etc/victoriametrics/vmagent/scrape.yml sudo cp vmctl-prod /usr/lib/victoriametrics/bin/
`scrape.yml` は `scrape_configs` 部分と global の scrape_interval だけのこす
[Unit]
Description=VictoriaMetrics service
After=network.target
[Service]
Type=simple
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/lib/victoriametrics/bin/victoria-metrics-prod \
-storageDataPath=/var/lib/victoriametrics \
-retentionPeriod=365d -selfScrapeInterval=10s
SyslogIdentifier=victoriametrics
Restart=always
PrivateTmp=yes
ProtectHome=yes
NoNewPrivileges=yes
ProtectSystem=full
[Install]
WantedBy=multi-user.target [Unit]
Description=vmagent
After=network.target
[Service]
User=victoriametrics
Group=victoriametrics
ExecStart=/usr/lib/victoriametrics/bin/vmagent-prod \
-promscrape.config=/etc/victoriametrics/vmagent/scrape.yml \
-remoteWrite.tmpDataPath=/var/tmp/vmagent/tmp/ \
-remoteWrite.url=http://localhost:8428/api/v1/write
Restart=on-failure
User=nobody
Group=nogroup
[Install]
WantedBy=multi-user.target sudo systemctl daemon-reload
sudo systemctl enable victoriametrics
sudo systemctl enable vmagent sudo systemctl start victoriametrics sudo systemctl status victoriametrics sudo systemctl start vmagent sudo systemctl status vmagent
curl -XPOST http://127.0.0.1:9090/api/v1/admin/tsdb/snapshot
{"status":"success","data":{"name":"20250516T103320Z-3bf4745e0d76170b"}}% (snapshot はハードリンクなだけなのでいらなくなったらディレクトリごと消せばよい)
sudo /usr/lib/victoriametrics/bin/vmctl-prod prometheus --prom-snapshot=/var/lib/prometheus/snapshots/20250516T103320Z-3bf4745e0d76170b
2025/05/16 19:33:50 ERROR: metrics: disable exposing PSI metrics because of failed init: open /sys/fs/cgroup/system.slice/ssh.service/cpu.pressure: no such file or directory
Prometheus import mode
Prometheus snapshot stats:
blocks found: 27;
blocks skipped by time filter: 0;
min time: 1714608000341 (2024-05-02T09:00:00+09:00);
max time: 1747391598321 (2025-05-16T19:33:18+09:00);
samples: 11071261940;
series: 135060.
Found 27 blocks to import. Continue? [Y/n] 結構時間がかかる。12GBで2時間弱ぐらい。インポート後は2.5GBになった。
sudo systemctl stop prometheus
sudo systemctl disable prometheus mqtt_topic_exporter という mqtt ブローカーに接続して特定の topic を subscribe して prometheus 形式で出すというのを、7年前に書いたまま放置していた。
放置といっても(珍しく)使ってなかったわけではなく、ビルド済みバイナリをずっと使い続けていた。けどまぁ7年も経過すると何もかもかわっており (当時 go.mod すらなかった)、現行のツールチェインではビルドできなくなっていたので、なおすことにした。
全体的に Copilot Agent に分からんこと聞いたり、やりたいことを指示するだけでほぼ完了させることができた。特にテストは自力で書こうと思うとダルすぎてたぶん一生やらなかった。「どうしたらいいかねえ」ぐらいのふわっとした段階から壁打ちして方針 (e2eだけテストしようとか) 決めて、雑に初期実装してくれるのはありがたい……
ただ今回、普通に指示するだけだとベタ書きする感じだったので、分けてほしい部分は個別に指示する必要があった。あとやっぱり普通に嘘をつかれる。「version.NewCollector() はなくなりました (正しくは別パッケージに移動)」とか